I have a template that inherits from another template, with itself as the second template's template parameter. The inherited template defines a static function:
template<class T> class A
{
public:
static void foo();
};
template<class T> class B : public A<B>
{
};
Now I want to implement the static function for the class A specialized with B, but with B not specialized. But I can't figure out how to declare the template. I'm not even sure if this is possible. My first try was:
template<class T> void A<B<T>>::foo()
{
}
But this gives the error:
"Nested name specifier 'A<B<T>>::" for declaration does not refer into a class, class template or class template partial specialization"
I've tried different things like adding "template<>" in front but none of those worked. I am able to compile this:
template<> void A<B<int>>::foo()
{
}
As well as this:
template<class T> void A<T>::foo()
{
}
Is this an attempt at partial specialization? My first impression is no (there are no templates with multiple parameters where I want to specialize one of them). Rather, I want to specialize a template with another template that is not specialized. Is this possible, and if so what is the proper syntax?
This is indeed partial specialization. You cannot partially specialize just a method, you must partially specialize the whole class. See this answer. You might try implementing foo in a separate helper struct and partially specializing that struct instead.
Here is an example using a helper struct.
#include <iostream>
template<class T> struct t_helper
{
static void foo()
{
std::cout << "Not B<T>\n";
}
};
template<class T> class A
{
public:
static void foo() {
t_helper<T>::foo();
}
};
template<class T> class B {};
// Specialize the behavior of A<T>::foo() for all B types
template<class T>
struct t_helper<B<T>>
{
static void foo()
{
std::cout << "Is B<T>\n";
}
};
int main()
{
A<int>::foo(); // Prints "Not B<T>\n"
A<B<int>>::foo(); // Prints "Is B<T>\n"
return 0;
}
Related
Can I call an unspecialized template method from a specialized one?
This is easy when using inheritance:
class SomeBaseClass {
virtual void DoWork() { /* Do something */ }
};
class SomeClass : public SomeBaseClass {
void DoWork() {
// Do something first
SomeBaseClass::DoWork();
}
};
But is a bit different when using templates:
template <class T>
class SomeClass {
void DoWork();
};
template<class T>
void SomeClass<T>::DoWork() { /* Do something */}
template<>
void SomeClass<int>::DoWork() {
// Do something first
DoWork<>(); // Call method from line 8
}
My generic DoWork function has a lot of really good code in it that I'd hate to duplicate. My specialized one just has an extra step that it needs to perform when a specific type is used.
Similar to here, you can do that indirectly:
template <class T>
class SomeClassCommonImpl {
void DoWork();
};
template<class T>
void SomeClassCommonImpl<T>::DoWork() { /* Do something */}
template <class T>
class SomeClass: public SomeClassCommonImpl<T> {
// use the default implementation
};
template <>
class SomeClass<int>: public SomeClassCommonImpl<int> {
void DoWork();
};
template<>
void SomeClass<int>::DoWork() {
// Do something first
SomeClassCommonImpl<int>::DoWork<>(); // Call the common method
}
You're thinking about this the wrong way.
The solution is not to have your class specialized, but to have your function specialized. What I mean here is to use tag dispatch
That is, declare two private helper functions in your class named DoWorkHelper, one of which is overloaded for the specialized type, and the other not.
The way we do this is to wrap our type in a 'tag' that is basically an empty struct, and then specialize the tag for our type of interest:
namespace SomeClassDetail{
template<class T>
struct specialized_tag : std::false_type{};
template<>
struct specialized_tag<int>: std::true_type{};
}
true_type and false_type are essentially wrappers for boolean true and false. They're nice because they're types and not values (and when we template we care all about types)
Next, we'll declare our class with aforementioned overloads:
template <class T>
class SomeClass {
public:
void DoWork();
private:
void DoWorkHelper(std::true_type);
void DoWorkHelper(std::false_type);
};
The idea here is that true_type means "Yes, this function is for the specialized version!"
Here's what the definitions look like:
template<class T>
void SomeClass<T>::DoWork()
{
DoWorkHelper(typename SomeClassDetail::specialized_tag<T>::type{});
}
template<class T>
void SomeClass<T>::DoWorkHelper(std::true_type)
{
std::cout << "Specialized DoWork\n";
DoWorkHelper(std::false_type());
}
template<class T>
void SomeClass<T>::DoWorkHelper(std::false_type)
{
std::cout << "Unspecialized DoWork\n";
}
That's it. The specialized version will do its thing, and then call the unspecialized version, and the unspecialized version (for all other T), will simply do its thing.
Here's a live demo that demonstrates tag dispatch in action
Given the following definitions:
template <typename T>
class A {
public:
void f();
};
template <typename T>
void
A<T>::f()
{}
template <typename T>
class B {};
How would I partially specialize A<B<T>>::f, i.e. f for some B<T>? I'm basically looking for the right magic to substitute the ??? below
template <???>
void
A<B<T>>::f()
{}
You can have an explicit specialization, from [temp.expl.spec]:
An explicit specialization of any of the following:
— ...
— member function of a class template
— ...
can be declared by a declaration introduced by template<>
That is:
template <>
void A<B<int>>::f() {
std::cout << "B\n";
}
But you cannot have a partial specialization of a member function of a class template. You would have to partially specialize the entire class:
template <typename T>
class A<B<T>> {
public:
void f() {
std::cout << "B\n";
}
// ... all other members you want in A<B<T>> ...
};
You cannot partially specialize a member function (nor in fact any function). You need to partially specialize the whole class:
template<typename T>
class A<B<T>>
{
// implement member functions for this specialization here
};
If you must have:
template <typename T>
void A<B<typename T>>::f() {}
then your only choice is to partially specialize A.
template <typename T> class A<B<T>>
{
public:
void f();
};
C++11 has Alias Templates, allowing you do do something like:
template<T>
using AB = A<B<T>>;
Then you can refer to AB<T> instead of A<B<T>>.
Unfortunately, you can't use that for specialization..
So seems to me the answer to your question is: You can't do that, but it's a shame.
Is following design possible?:
template <typename T>
class Test{
public:
template <typename Z>
void doSomething();
//rest of things
private:
T obj;
//some things
};
Now if it was possible I'd do some explicit specializations for doSomething so that at the end I'd have some versions like below:
void doSomething<int>(){
//do something
}
void doSomething<double>(){
//do something
}
...etc
which seems impossible I can't find any syntax to do the job then I thought maybe the design should be as it follows so that all template arguments should be passed to template class itself:
template <typename T,typename Z>
class Test{
public:
void doSomething();
//rest of things
private:
T obj;
//some things
};
Then I tried partial specialization which didn't even compile:
template <typename T>
void Test<T,int>::doSomething(){
//do something
}
template <typename T>
void Test<T,double>::doSomething(){
//do something
}
...etc
I got the following errors for explicit specialization:
error#1:template argument list following class template name must list parameters in the order used in template parameter list.
error#2:'Container1' :too few template arguments.
In order to explicitly specialize doSomething you have to also explicitly specialize Test.
From 14.7.3/18 :
In an explicit specialization
declaration for a member of a class
template or a member template that
appears in namespace scope, the member
template and some of its enclosing
class templates may remain
unspecialized, except that the
declaration shall not explicitly
specialize a class member template if
its enclosing class templates are not
explicitly specialized as well.
You cannot explicitly specialize a member template unless its enclosing class templates are also explicitly specialized.
So only something like this will work:
template<> template<>
void Test<int>::doSomething<int>()
{
}
you can always make the function inline
template <class T>
class Test
{
public:
template <class Z>
void doSomething() { cout << "default" << endl; }
template<>
void doSomething<int>() { cout << "int" << endl;}
template<>
void doSomething<double>() { cout << "double" << endl; }
private:
T obj;
};
I think this one is picky. I suppose you can't do it, read this.
Not sure if this is a bug in g++ but this compiles and produce what I expect.
#include<typeinfo>
#include<iostream>
template<typename T>
class Test
{
public:
template<typename Z>
void doSomething();
private:
T obj;
};
template<typename T>
template<typename Z>
void Test<T>::doSomething()
{
Z val;
std::cout << __func__ << ": type " << typeid(val).name() << std::endl;
}
int main(int argc, char *argv[])
{
Test<double> a;
a.doSomething<int>();
a.doSomething<double>();
}
icecrime posted a temporary answer and it gets compiled due to some bug probably by visual C++ 2008:
template <typename T>
class Test{
public:
template <typename Z>
void doSomething();
//rest of things
private:
T obj;
//some things
};
template <>
template <typename T>
void Test<T>::doSomething<int>(){
//do something
}
Check his current answer though.
The funny thing at least with VC++ 2008 is, no problem compiling when specializing with inline definitions, but for specializations with not-inline definitions once there's more than one version it doesn't get compiled successfully.
Is there a partial specialization for template class method?
template <class A, class B>
class C
{
void foo();
}
it doesn't work to specialize it like this:
template <class A> void C<A, CObject>::foo() {};
Any help?
If you are already have specialized class you could give different implementation of foo in specialized class:
template<typename A, typename B>
class C
{
public:
void foo() { cout << "default" << endl; };
};
template<typename A>
class C<A, CObject>
{
public:
void foo() { cout << "CObject" << endl; };
};
To specialize member function in Visual C++ 2008 you could make it template too:
template<typename A, typename B>
class C
{
template<typename T>
void foo();
template<>
void foo<CObject>();
};
The solution above seems to will be available only in future C++ Standard (according to draft n2914 14.6.5.3/2).
I think there is a misunderstanding there.
There are two kinds of templates:
the template classes
the template methods
In your example, you have a template class, which of course contains some methods. In this case, you will have to specialize the class.
template <class A>
class C<A,CObject>
{
void foo() { ... } // specialized code
};
The problem in your example is relatively simple: you define the method foo for the specialization C but this specialization has never been declared beforehand.
The problem here is that you have to fully specialize your C class (and thus copying a lot of data). There are a number of workarounds.
Inheritance (Composition ?): do all the common work in a base class, then have the C class inherits and specialize as appropriate
Friend: instead of having the 'foo' method being a member of C, define it as a friend free functions and specialize only this method
Delegation: have your 'foo' method call another method 'bar', which is a free function, and specialize 'bar' appropriately
Which in code gives:
// 1- Inheritance
template <class A, class B>
class CBase
{
// Everything that does not require specialization
};
template <class A, class B>
class C: public CBase<A,B>
// depending on your need, consider using another inheritance
// or even better, composition
{
void foo(); // generic
};
template <class A>
class C<A,CObject> : public CBase<A,CObject>
{
void foo(); // specialized
};
// 2- Friend
// note the change in signature:
// - now you need to pass the attributes to be changed
// - the last parameter helps differentiating the overload
// as there is no specialization for functions
template <class A, class B> void foo(Arg1&, Arg2&, const B&);
template <class A> void foo(Arg1&, Arg2&, const CObject&);
template <class A, class B>
class C
{
friend template <class, class> foo;
};
// 3- Delegation
// same signature as foo in (2)
template <class A, class B> void bar(Arg1&, Arg2&, const B&);
template <class A> void bar(Arg1&, Arg2&, const CObject&);
template <class A, class B>
class C
{
void foo() { bar(member1, member2, B()); }
};
Hope it clarifies, and helps!
No, there is no partial function template specialization in C++0x to be added.
As correctly mentioned above, with regards to function templates basically 2 things were done:
default template arguments were made available;
variadic templates were introduced.
So as before, workarounds should be used to "emulate" partial function templates specialization.
Since the class is the template, you need to specialize that:
template <class A>
class C<A, CObject>
{
void foo() { ... }
}
If I remember correctly, you cannot make partial template specialization for functions. Not sure whether it is included in C++0X
Update:
(Awaiting confirmation) As noted in the comments, partial template specialization of functions is possible in C++0X.
A method template may delegate to (static) methods of partially specialized classes or structs. Template parameters in the outer class are not helpful for answering the question.
class ClassWithSpecializedMethodEmulation
{
private:
template <typename A, typename B> struct Calculator;
public:
template <typename A, typename B> A evaluate(A a, B b)
{
return Calculator<A,B>::evaluate(a,b);
}
private:
template <typename A, typename B> struct Calculator
{
// Common case: multiply
static A evaluate(A a, B b)
{
return (A)(a*b);
}
};
// with double argument a do something else
template <typename B> struct Calculator<double, B>
{
static double evaluate(double a, B b)
{
return (double)(a - b);
}
};
};
In case the method requires access to class members, struct Calculator additionally must be friend of ClassWithSpecializedMethodEmulation and get a this-pointer passed.
Can you specialize a template method within a template class without specializing the class template parameter?
Please note that the specialization is on the value of the template parameter, not its type.
This seems to compile under Visual Studio 2008 SP1 complier, but not GCC 4.2.4.
#include <iostream>
using namespace std;
template <typename T>
class A
{
private:
template <bool b>
void testme();
template <>
void testme<true>() { cout << "true" << endl; };
template <>
void testme<false>() { cout << "false" << endl; };
public:
void test();
};
template<typename T> struct select {};
template<> struct select<int> { static const bool value = true; };
template<> struct select<double> { static const bool value = false; };
template <class T>
void A<T>::test() { testme<select<T>::value>(); }
int main(int argc, const char* argv[])
{
A<int> aInt;
A<double> aDouble;
aInt.test();
aDouble.test();
return 0;
}
GCC tells me:"error: explicit specialization in non-namespace scope ‘class A’"
If it is not supported in the standard, can anyone tell me why?
It is not supported in the standard (and it is apparently a known bug with Visual Studio that you can do it).
The standard doesn't allow an inner template (member function or class) to be specialized without the outer template being specialized as well. One of the reasons for this is that you can normally just overload the function:
template<typename ty>
class A
{
public:
void foo(bool b);
void foo(int i);
};
Is equivalent to:
template<typename ty>
class A
{
public:
template<typename ty2>
void foo(ty2);
template<>
void foo(bool b);
template<>
void foo(int i);
};
here is how you do it:
template<typename A>
struct SomeTempl {
template<bool C> typename enable_if<C>::type
SomeOtherTempl() {
std::cout << "true!";
}
template<bool C> typename enable_if<!C>::type
SomeOtherTempl() {
std::cout << "false!";
}
};
You can get enable_if from my other answer where i told them how to check for a member function's existance in a class using templates. or you can use boost, but remember to change enable_if to enable_if_c then.
Here is another workaround, also useful when you need to partialy specialize a function (which is not allowed). Create a template functor class (ie. class whose sole purpose is to execute a single member function, usually named operator() ), specialize it and then call from within your template function.
I think I learned this trick from Herb Sutter, but do not remember which book (or article) was that. For your needs it is probably overkill, but nonetheless ...
template <typename T>
struct select;
template <bool B>
struct testme_helper
{
void operator()();
};
template <typename T>
class A
{
private:
template <bool B> void testme()
{
testme_helper<B>()();
}
public:
void test()
{
testme<select<T>::value>();
}
};
template<> void testme_helper<true>::operator()()
{
std::cout << "true" << std::endl;
}
template<> void testme_helper<false>::operator()()
{
std::cout << "false" << std::endl;
}
I've never heard of that being possible; it would make sense to me if it was not supported by all compilers. So here is an idea for a workaround:
Implement a template function outside of your class which takes the same action as the method. Then you can specialize this function, and it call it from the method. Of course, you'll also have to pass in any member variables that it needs (and pointers thereto if you want to modify their values).
You could also create another template class as a subclass, and specialize that one, although I've never done this myself and am not 100% sure it would work. (Please comment to augment this answer if you know whether or not this second approach would work!)