8

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?

user231536
  • 2,661
  • 4
  • 33
  • 45

2 Answers2

5

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.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I don't think he's even trying to specialize. Edit: Ah right, by "partial specialization" he wants to omit one of the parameters. – someguy Jan 03 '12 at 21:31
  • So there is no way to partially specialize a member method of a template class, without specializing the whole class itself? – user231536 Jan 03 '12 at 21:40
  • @user231536: No, indeed. Here's a [similar, previous answer](http://stackoverflow.com/a/7517290/596781). – Kerrek SB Jan 03 '12 at 21:54
1

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)

Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
  • I think that some combination of @KerreckSB's answer, and maybe mine, might be correct. I'm not sure what the ultimate goal is. Ultimately, I think a totally-unspecialized `foo1()` will need to be implemented sooner or later, like the one I have written. – Aaron McDaid Jan 03 '12 at 23:30