partial template member specialization - c++

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.

Related

How to define a template specialization for a templated function for a templated class

I have a class, something like BizClass below. I'd like to define a templated function and a specialization for a particular concrete type. I'm not sure of the appropriate syntax.
template <class Foo>
class BizClass {
public:
template <typename Bar>
void Action(Container<Bar> m);
// Foo is used somewhere else...
};
// This seems to work.
template <class Foo>
template <typename Bar>
inline void BizClass<Foo>::Action(Container<Bar> m) {}
// This specialization doesn't compile, where Foobar is a concrete class.
template <class Foo>
inline void BizClass<Foo>::Action(Container<FooBar> m) {}
How do I handle the template specialization for this case?
In your first code sample titled This seems to work., that is just defining the body for the template function, it is not a specialization.
In the second sample you attempt to specialize a template which is a member of another unspecialized template. This is not allowed.
You need to also specialize BizClass if you want to specialize Action, e.g. here is an example with Foo=int and Bar=char:
template<> template<>
inline void BizClass<int>::Action(Container<char> m)
{
}
How do I handle the template specialization for this case?
As far I know, the C++ forbids specialization of a method, inside a template struct/class, without specializing the struct/class itself.
But you can use overloading: make Action (Container<FooBar> m) a not-template method
#include <iostream>
template <typename>
struct Container
{ };
struct FooBar
{ };
template <typename Foo>
struct BizClass
{
template <typename Bar>
void Action (Container<Bar> m);
void Action (Container<FooBar> m);
};
template <typename Foo>
template <typename Bar>
inline void BizClass<Foo>::Action (Container<Bar> m)
{ std::cout << "Action() generic version" << std::endl; }
template <typename Foo>
inline void BizClass<Foo>::Action (Container<FooBar> m)
{ std::cout << "Action() FooBar version" << std::endl; }
int main ()
{
BizClass<int> bci;
bci.Action(Container<int>{}); // print Action() generic version
bci.Action(Container<FooBar>{}); // print Action() FooBar version
}

Template Specialization with Template for Static Function

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;
}

specializing template member function to work in a different way for a special template class

I have two classes class A and class B both of them are template classes for a member function in A I want it to act in a special way when the type of A is B
and in a normal way for any other types I don't know how to do this ?
template <class B>
class B
{
private:
T m;
public:
...... any member functions
}
template <class T>
class A
{
private:
T var;
public:
void doSomething();
};
template <class T>
void A<T>::doSomething(){...........//implementation}
template <class T>
void A<B<T>>::doSomething(){................//different implementation}
You can specialize A this way:
template <class T>
class A<B<T>> {
// ...
};
This is an instance of partial template specialization.
If you refuse to specialize the entire class, you can defer the work from A<T>::doSomething() to a function doSomethingForA<T>(A &) that would be partially specialized, and that would possibly be friend of A<T>.
Hope this solves your problem:
#include <iostream>
template <typename T>
struct B {};
template <typename T> struct A;
template <typename T>
void doSomething(T&) { std::cout << "General\n"; }
template <typename T>
void doSomething(A<B<T>>&) { std::cout << "Special\n"; }
template <typename T>
struct A {
void doSomething() {
::doSomething(*this);
}
};
int main()
{
A<int> general;
A<B<int>> special;
general.doSomething();
special.doSomething();
}

member-template specialization

template<typename T>
class C
{
void f() { }
};
/*template<typename T>
void C<T*>::f() { }*/
template<>
void C<int*>::f() { }
If we remove comment, code will not compile. I know this (and i also know, that we should have partial specialization for C<T*>), but I cannot find words in standard, which explains such behaviour. I reread 14 par of standard few times. Can you give me a quote or par of standard, that explains this?
EDIT.
template<typename T>
class C
{
template<typename U>
struct S { };
};
// #1
/*template<typename T>
class C<T*>
{
template<typename U>
struct S { };
};*/
// #2
/*template<typename T>
template<typename U>
struct C<T*>::S<U*> { };*/
template<>
template<typename U>
struct C<int*>::S<U*> { };
If we remove only comment next then #2 - code will not compile.
Here is the standard quote about what may be specialized expliclitly, from 14.7.3/1:
An explicit specialization of any of the following:
— function template
— class template
— member function of a class template
— static data member of a class template
— member class of a class template
— member enumeration of a class template
— member class template of a class or class template
— member function template of a class or class template
can be declared by a declaration introduced by template<>;
Unless explicitly allowed, you cannot partially specialize anything, and member functions of class templates are not explicitly allowed. Only class templates may be specialized partially (as described in 14.5.5).
(Note that a member class template of an explicitly specialized class template is itself a class template.)

C++ partial method specialization

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.