The following code:
using namespace std;
template <typename X>
class Goo {};
template <typename X>
class Hoo {};
template <class A, template <typename> class B = Goo >
struct Foo {
B<A> data;
void foo1();
void foo2();
};
template <typename A>
void Foo<A>::foo1() { cout << "foo1 for Goo" << endl;}
int main() {
Foo<int> a;
a.foo1();
}
gives me a compiler error:
test.cc:18: error: invalid use of incomplete type 'struct Foo<A, Goo>'
test.cc:11: error: declaration of 'struct Foo<A, Goo>'
Why can't I partially specialize foo1() ? If this is not the way, how do I do this?
I have another question: what if I want foo2() to be defined only for A=int, B=Hoo and not for any other combination, how do I do that?
Template partials are small bits of reusable template or tag parts. You could create a Template partial for any number of purposes, anywhere that you need to reuse a small portion of a template, including partial or complete tags, other variables, etc.
You can choose to specialize only some of the parameters of a class template. This is known as partial specialization. Note that function templates cannot be partially specialized; use overloading to achieve the same effect.
For normal code, you would use a class template when you want to create a class that is parameterised by a type, and a function template when you want to create a function that can operate on many different types.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
Function templates may only be fully specialized, not partially.
Member functions of class templates are automatically function templates, and they may indeed be specialized, but only fully:
template <>
void Foo<int, Goo>::foo1() { } // OK
You can partially specialise the entire class and then define it anew:
template <typename A>
struct Foo<A, Goo>
{
// ...
};
(See 14.7.3 for details.)
The template still has two parameters, and you must write something like this:
template <typename A, template <typename> class B>
void Foo<A,B>::foo1() { cout << "foo1" << endl;}
The default has been specified, and only needs to be specified once. From then on, it's just like any other two-parameter template. This code will apply no matter what B is (defaulted or otherwise). If you then wish to specify different behaviour for a particular B, then you do specialization of the class, not just of a method.
(Heavily edited)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With