C++ - Template Specialization & Partial Specialization - c++

I have been looking all over the internet and stackoverflow for a concrete answer but I can't seem to find one. I have to create a generic class and then implement specific functions. My specific instructions were: You need to make use of Template Expression Parameters and Template Class Specialization and Partial Specialization.
I have a template class:
template <class T, int x, int y>
class Z {
T **array[x][y];
public:
Z();
void print();
//and other methods
};
I need to:
1) Only Z's where x= 2 and y = 2 need to have a public method void J()
2) For char Z's of x = 2 and y= 2 J will do something; for everything else it does something else
3) For only Z's where T is char will the array be initialized to some value. For everything else it's 0
Naturally, this works:
template<class T, int x, int y>
Z<T,x,y>::Z<T,x,y>() { //initialize to 0 }
But this doesn't:
template<int x, int y>
Z<char,x,y>::Z<char,x,y>() { //initialize to something}
And likewise (assume J exists) this does not work:
template <class T>
void Z<T,2,2>::J() { //something }
My question is:
Is there any simple method for implementing the above items? I need to keep all the other methods in Z. Giving a hint or pointing in the right direction (maybe I missed a question since there are a lot) would be helpful.
Thanks.

It seems you want to define only some functions of some specializations : if print() does not change between the char specialization and the general case, it seems that you don't want to redefine it.
// What you want to do (illegal in C++)
template<int,typename T>
struct Z
{
T myValue;
Z();
void print() { /* ... */ }
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }
template<int i>
Z<i,char>::Z() { /* ... */ }
However, it does not work like this. Partial or full specializations of class have almost nothing in common, except 'prototype' of template parameters:
// The two following types have only two things related: the template parameter is an int,
// and the second type is a full specialization of the first. There are no relations between
// the content of these 2 types.
template<int> struct A {};
template<> struct A<42> { void work(); };
You have to declare and define each (partial) specialization:
// Fixed example
template<int,typename T>
struct Z
{
T myValue;
Z();
void print() { /* ... */ }
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }
// Specialization for <all-ints,char>
template<int i>
struct Z<i,char>
{
char myValue;
char othervalue;
Z();
void print() { /* Same code than for the general case */ }
};
template<int i>
Z<i,char>::Z() { /* ... */ }
The only way to escape the code duplication is by using inheritance of traits:
// Example with the print function
template<typename T>
struct print_helper
{
void print() { /* ... */ }
};
// Fixed example
template<int,typename T>
struct Z : public print_helper<T>
{
T myValue;
Z();
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }
// Specialization for <all-ints,char>
template<int i>
struct Z<i,char> : public print_helper<char>
{
char myValue;
char othervalue;
Z();
};
template<int i>
Z<i,char>::Z() { /* ... */ }
You cannot do what you want without duplication for the moment (the feature removing code duplication is static if and has been proposed for the next C++ standard, see n3322 and n3329).

You may have a look at this course http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-5-of-n
While this is not possible that you define partial specialization for function templates, you can define partial specialization for class or struct template.
template<typename T> struct helper {
static void doThingy(){}
};
template<typename X> struct helper<X*> {
static void doThingy(){}
};
Helper(double*)::doThingy();
In this example, you want to specialize behavior in doThingy() only when the type in template is a pointer type. You cannot use overload of method doThingy() in this case. This is because you cannot overload a function with no arguments. But you can have partial specialization of the struct helper. In specialized template, you implemented wished behavior for the doThingy().

Related

How to specialize a non-templated-member function of a template class for multiple types?

I'm biting of my nails on the syntax required to partially specialize a member function for multiple types. Here is what I have:
#include <cstdint>
#include <string>
class Property
{
public:
virtual int read(uint8_t *) = 0;
};
template<typename T>
class PropertyValue
{
T value_;
public:
int read(uint8_t *);
};
// specialized for std::string
template<>
int PropertyValue<std::string>::read(uint8_t *buf) { /* put string-value to buf */}
Now I would want to specialize the read-function for different enum-types. I tried a combination of enable_if and is_same which looks promissing, then putting it inside the template-declaration (compiler told me there are now 2 template arguments whereas 1 was expected).
Putting it inside the class-definition was not working either. Outside ... well, here's what I currently have.
// specialize for some enums
template<typename T>
typename std::enable_if<std::is_same<T, enum Enum1>::value ||
std::is_same<T, enum Enum2>::value, int>::type
PropertyValue<T>::read(uint8_t *buf)
{
return encode_enum(buf, value_);
}
Where is my thinking wrong?
EDIT: Writing it like this compiles and works:
template<>
int PropertyValue<Enum 1>::read(uint8_t *buf)
{
return encode_enum(buf, value_);
}
template<>
int PropertyValue<Enum 2>::read(uint8_t *buf)
{
return encode_enum(buf, value_);
}
PropertyValue::value itself is not a template. It's not a template class, it's not a template function. It's a member of a template class, which is not the same thing as being a template itself.
You have to specialize the entire class.
template<>
class PropertyValue<std::string>
{
std::string value_;
public:
int read(uint8_t *)
{
// Your specialization goes here.
}
};
Even if read() itself was a template, you must still specialize its class, before you can specialize a template class's template member.
Of course, if your template class has many other members and methods, every one of them have to be specialized here, leading to plenty of code getting duplicated. At that point, you will be faced with several options for refactoring out that duplicated code. The best approach for that depends on the particular details.
But that's how it's done...
EDIT: one common approach is to use a helper template class:
template<typename T> class PropertyValue; // Forward declaration
template<typename T> class do_read {
public:
static int do_it( PropertyValue<T> &me, uint8_t *p )
{
// your default implementation
}
};
template<> class do_read<std::string> {
public:
static int do_it( PropertyValue<std::string> &me, uint8_t *p )
{
// your specialization
}
};
template<typename T>
class PropertyValue
{
T value_;
public:
int read(uint8_t *p)
{
return do_read<T>::do_it(*this, p);
}
};

Simplify large number of template specializations

So I have a tremendous number of template specializations of this template:
template <typename T> // Same
struct foo { // Same
using type_name = T; // Same
foo(const int base) : _base(base) {} // May take other parameters
void func(const T& param) {} // This function signature will be the same but body will differ
int _base; // Same but may have more members
}; // Same
So an example specialization would be:
template<>
struct foo<float> {
using type_name = T;
foo(const int base, const int child) : _base(base), _child(child) {}
void func(const T& param) { cout << param * _child << endl; }
int _base;
int _child;
};
Obviously this is a toy example and the body of _func will be more involved. But I think this expresses the idea. I can obviously make a macro to help with the boilerplate and put the implementation of the specialized version of the function in an implementation file.
But I was hoping that C++ provided me a way to do this without macros. Is there another way for me avoid writing the boilerplate over and over?
you can have multiple specialization for the function but not for the whole class
like this
#include <iostream>
#include <string>
template<typename T>
struct foo {
//common generic code
using type_name = T;
foo(const int base, const int child) : _base(base), _child(child) {}
void func(const T& param);
int _base;
int _child;
};
template<>
void foo<float>::func(const type_name&) {
//implementation
std::cout << "float" << std::endl;
}
template<>
void foo<int>::func(const type_name&) {
//implementation
std::cout << "int" << std::endl;
}
int main() {
foo<int> tint(0, 0);
foo<float> fint(0, 0);
tint.func(0);
fint.func(0);
}
You can use some light inheritance of data structs to help you separate the differences in member layout and constructor definitions from the main template.
//Define an internal aggregate type you can specialize for your various template parameters
template <typename T>
struct foo_data {
foo(const int base) : _base(base) {}
int _base;
};
//Then derive privately from the data struct (or publicly if you really desire)
template <typename T>
struct foo : private foo_data<T> {
using type_name = T;
using foo_data<T>::foo_data<T>; //Make the base class constructors visible
void func(const T& param); //Use member specialization as suggested by the other answer
};
I will leave it to you to decide if it is better this way or not, but the upshot is that all the common parts are completely separated from all the uncommon parts.
In a comment under another answer I erroneously described this as CRTP. It isn't and it doesn't have any of the drawbacks as CRTP.
If you really need to preserve standard layout, then you can simulate inheritance manually with explicit delegation and perfect forwarding.
template <typename T>
struct foo {
using type_name = T;
template <typename... Args>
foo(Args&&... args) : base_data_(std::forward<Args>(args)...) {}
void func(const T& param); //Use member specialization as suggested by the other answer
foo_data<T> base_data_;
};
One drawback is I don't think the delegating constructor will SFINAE properly as written, and it also eats noexcept specifiers and explicit. Fixing those issues(if required) is left as an exercise to the reader.
There is no nice way to avoid some redundancy in notation when implementing specializations of templated types. There are some techniques to avoid duplication of actual code, such as
Using a traits template to provide type-specific things
template<typename T>
struct foo_traits { ... }; // provide many specialisations
template<typename T> // no specialisations
struct foo
{
using traits = foo_traits<T>;
template<typename...Aars>
explicit foo(Args&&...args)
: data(std::forward<Args>(args)...) {}
int do_something_specific(T x)
{ return traits::do_something(data,x); }
private:
typename traits::data data;
};
a very similar approach is to use a specialized base class:
template<typename T>
struct foo_base { ... }; // provide many specialisations
template<typename T> // no specialisations
struct foo : foo_base<T>
{
using base = foo_base<T>;
template<typename...Aars>
explicit foo(int m, Args&&...args)
: base(std::forward<Args>(args)...)
, more_data(m) {}
int do_something_specific(T x)
{ return base::do_something(x,more_data); }
private:
int more_data;
};
The constructor of foo is a variadic template in order to allow the base class's constructor to take any number and type of arguments.
Of you can use a common base class and specialize the derived classes. This can be done with the Curiously recurring template pattern (CRTP)
template<typename Derived>
struct foo_base // no specializations
{
using type = typename Derived::type;
int do_something(type x)
{
auto result = static_cast<Derived*>(this)->specific_method(x);
return do_some_common_stuff(result);
}
protected:
foo_base(type x) : data(x) {}
type data;
private:
int do_some_common_stuff(type x)
{ /* ... */ }
};
template<typename T> // some specialisations
struct foo : foo_base<foo<T>>
{
using base = foo_base<foo>;
using type = T;
using common_type = typename base::common_type;
using base::do_something;
explicit foo(type x, type y)
: base(x), extra_data(y) {}
protected:
type specific_method(type x)
{ /* ... */ }
private:
type extra_data;
};
Note that foo_base is already a template (unlike the situation with ordinary polymorphism), so you can do a lot of specific stuff there already. Only things that are done differently (not merely with different types) need specializations of foo.
Finally, you can combine these approaches, for example traits classes with CRTP.
All these methods implement some type of static or compile-time polymorphism, rather than real or dynamic polymorphism: there are no virtual functions and hence no virtual table and no overhead for table look-up. It is all resolved at compile time.
This is usually done through inheritance - you put the immutable part into base class, and specialize the children.
I do not think you need an example for that, but let me know if you do.

How does one specialize a template for all non-array types?

Let's say I have a template my_type. I want it to have general functionality, to have a few extra functions when T is not an array and to have others when T is an array.
Let's say I have the following template:
template <typename T>
class my_class<T> {
public:
int f1(); // This function is available for all T
int f2(); // This function is available when T is not an array
int f3(); // This function is available when T is an array
}
So if I try:
my_class<int> c1; my_class<int[3]> c2;
c1.f1(); c2.f1(); // both fine
c1.f2(); c2.f3(); // both fine
c1.f3(); c2.f2(); // both should give a compile error
I am aware std::unique_ptr does this internally. So how does it do it?
Another way, using enable_if. Note also the use of a base class to capture all common behaviour.
#include <type_traits>
template<class T>
struct my_base
{
int f1();
};
template<class T, typename Enable = void>
class my_class;
template<class T>
class my_class<T, std::enable_if_t<std::is_array<T>::value>>
: public my_base<T>
{
public:
int f3(); // This function is available when T is an array
};
template <typename T>
class my_class<T, std::enable_if_t<not std::is_array<T>::value>>
: public my_base<T>
{
public:
int f2(); // This function is available when T is not an array
};
int main()
{
auto a = my_class<int[]>();
a.f1();
// a.f2();
a.f3();
auto na = my_class<int>();
na.f1();
na.f2();
// na.f3();
}
I have figured it out myself. The following code will do the exact thing I have asked for.
template<typename T>
class my_class {
public:
int f1() { return 1; }
int f2() { return 2; }
};
template<typename T>
class my_class<T[]> {
public:
int f1() { return 1; }
int f3() { return 3; }
};
Note that the implementation of the common function (f1) had to be copied. Now is there a way to use a single implementation? (note that it is NOT as simple as a return 1; like in the example code and thus I can't separate functionality into a non-template function)

C++ template when the template's function is not the same

Now I have a template class
template <class T>
class b
{
void someFunc() {
T t;
t.setB();
}
};
I know the template T only will be instantiated into 2 classes.
class D
{
public:
void setB();
};
class R
{
public:
void SetB();
};
As we can see, class D's function name setB is not the same as R's function SetB. So in template class b I cannot only just use setB. So is there some method if I cannot revise D or R? Can I add some wrapper or trick into the template class to solve this problem?
Maybe a trait class can help you:
struct Lower {};
struct Upper {};
// trait for most cases
template <typename T>
struct the_trait {
typedef Lower Type;
};
// trait for special cases
template <>
struct the_trait<R> {
typedef Upper Type;
};
template <class T>
class b {
public:
void foo() {
foo_dispatch(typename the_trait<T>::Type());
}
private:
void foo_dispatch(Lower) {
T t;
t.setB();
}
void foo_dispatch(Upper) {
T t;
t.SetB();
}
};
As #Arunmu pointed, this technique is also known as Tag Dispatching.
You can specialise your template for the class that has different semantics:
template<>
class b<R>
{
void doWork() {
R obj;
obj.SetB();
// or R::SetB() if it was a static method.
}
};
Instead of using self programmed traits you can also check for the existence of a function with SFINAE.
If you want to switch your called method only one of them must exist in each class. My method provided will not work if the check find more then one of the tested methods!
The following example is written for C++14 but can also be used with c++03 if you replace the new library functions with self implemented ones ( which is of course not convenient )
The testing class has_Foo and has_Bar can also be embedded in a preprocessor macro, but I wrote it expanded to makes the things easier to read.
How it works and why there are some more intermediate steps are necessary are explained in the comments. See below!
#include <iostream>
// First we write two classes as example. Both classes represents
// external code which you could NOT modify, so you need an
// adapter to use it from your code.
class A
{
public:
void Foo() { std::cout << "A::Foo" << std::endl; }
};
class B
{
public:
void Bar() { std::cout << "B::Bar" << std::endl; }
};
// To benefit from SFINAE we need two helper classes which provide
// a simple test functionality. The solution is quite easy...
// we try to get the return value of the function we search for and
// create a pointer from it and set it to default value nullptr.
// if this works the overloaded method `test` returns the data type
// one. If the first test function will not fit, we cat with ... all
// other parameters which results in getting data type two.
// After that we can setup an enum which evaluates `value` to
// boolean true or false regarding to the comparison function.
template <typename T>
class has_Foo
{
using one = char;
using two = struct { char a; char b;};
template <typename C> static one test( typename std::remove_reference<decltype(std::declval<C>().Foo())>::type* );
template <typename C> static two test( ... ) ;
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(test<T>(0)) == sizeof(one) };
enum { No = !Yes };
};
template <typename T>
class has_Bar
{
using one = char;
using two = struct { char a; char b;};
template <typename C> static one test( typename std::remove_reference<decltype(std::declval<C>().Bar())>::type* );
template <typename C> static two test( ... ) ;
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(test<T>(0)) == sizeof(one) };
enum { No = !Yes };
};
// Now in your adapter class you can use the test functions
// to find out which function exists. If your class
// contains a Foo function the first one compiles and if the
// the class contains a Bar function the second one fits. SFINAE
// disable the rest.
// We need a call helper here because SFINAE only
// fails "soft" if the template parameter can deduced from the
// given parameters to the call itself. So the method
// Call forwards the type to test "T" to the helper method as
// as explicit parameter. Thats it!
template <typename T>
class X: public T
{
public:
template < typename N, std::enable_if_t< has_Foo<N>::value>* = nullptr>
void Call_Helper() { this->Foo(); }
template < typename N, std::enable_if_t< has_Bar<N>::value>* = nullptr>
void Call_Helper() { this->Bar(); }
void Call() { Call_Helper<T>(); }
};
int main()
{
X<A> xa;
X<B> xb;
xa.Call();
xb.Call();
}

Variadic template type unpacking into map keys

I'm trying to create a class which will contain a map of type_index keys mapped to pointers of each type passed as a template argument. This would allow me to specify a series of types my class will rely on in it's declaration.
I've done a bit of research but can only seem to find ways to unpack arguments, rather than types. I'm new to this subject, and would appreciate any clarification on terminology, or references to relevant text.
template <typename T>
T* SomeFakeFactoryGetter() { return new T(); }
template <class... Injected>
class UtilityProvider
{
public:
template <class U>
U* GetUtility()
{
std::type_index idx = std::type_index(typeid(U));
assert(_injectedClasses.find(idx) != _injectedClasses.end());
return reinterpret_cast<U*>(_injectedClasses[idx]);
}
// **
// How would I *unpack* all types for use as indices into my map?
// ( I realise this function is not what I want.)
template <Injected... C>
void Unpack()
{
_injectedClasses[std::type_index(typeid(C))] = SomeFakeFactoryGetter<C>();
}
private:
typedef std::unordered_map<std::type_index, void*> InjectedMap;
InjectedMap _injectedClasses;
};
class Bar{ public: void A() { printf("Hello bar"); } };
class Baz{ public: void B() { printf("Hello baz"); } };
class Nope {};
class Foo : public UtilityProvider<Bar, Baz>
{
public:
Foo()
{
GetUtility<Bar>()->A();
GetUtility<Nope>(); // Fail. User must specify which utilities this class will use.
}
};
What I've done in this situation is to create a dummy function to expand these expressions into, but it looks quite hideous:
template <int ... Dummies>
void dummy(int&& ...){}
template <class ... C>
void Unpack()
{
dummy(((_injectedClasses[std::type_index(typeid(C))] =
SomeFakeFactoryGetter<C>()), 0)...);
}
Note that in your case I think you'll be better off with using insert with an initializer_list:
template <class ... C>
void Unpack()
{
_injectedClasses.insert({std::make_pair(std::type_index(typeid(C)),
SomeFakeFactoryGetter<C>())...});
}
I couldn't find a direct mention of this but I believe there is an important difference between the two methods, in case you didn't already know. insert will not override existing key-value pairs, whereas operator[] will. This can affect which method you should use if if this is important to you.
An alternative approach:
template <typename ... C> struct Unpacker;
template <typename Tail, typename ... Queue>
struct Unpacker<Tail, Queue...>
{
void operator () (InjectedMap& injectedClasses) const
{
_injectedClasses[std::type_index(typeid(Tail))] = SomeFakeFactoryGetter<Tail>();
Unpacker<Queue...>()(injectedClasses);
}
};
template <>
struct Unpacker<>
{
void operator () (InjectedMap& injectedClasses) const {}
};