2

Foo.h

template<typename A, typename B>
class Foo{
public:
  Foo();
  /*..*/
};

Foo.cpp

template<typename A, typename B>
Foo<A, B>::Foo(){/*...*/}

template<typename A>
Foo<A, Beta>::Foo(){/* some specialized construction */} //<- this doesn't work.

template<>
Foo<Alpha, Beta>::Foo(){/*...*/} // <-will work, but I want partial specialization.

When I compile, the partially specialized constructor throws an error

nested name specifier 'Foo::' for declaration does not refer into a class, class template or class template partial specialization

I imagine I need to declare this partially-specialized class somewhere, but I don't want to have to keep re-declaring the same class ... ie I don't want to have to put the following in the header file:

template<typename A>
class Foo_Beta : public Foo<A, Beta>{
public:
  Foo_Beta();
}

//in cpp
template<typename A>
Foo_Beta<A>() : Foo<A, Beta>() {/**specialized constructor stuff**/}

Because then I can't construct Foo() that uses the Foo_Beta constructor.

I've tried

template<typename A>
class Foo<A,Beta> : public Foo<A, Beta>{
public:
  Foo();
}

but that doesn't compile either.

Essentially, what is the syntax to declare the partial specialization of a class without re-declaring all the internal functions to that class?

shavera
  • 803
  • 1
  • 8
  • 18
  • 3
    A partial specialization is still a template; why would you put it in a .cpp file? Anyway, the question seems to be more about how to partially specialize a member function of a class template without replacing the entire class. Unfortunately, this is not possible. You can't partially specialize function templates, and that includes member functions of class templates. – Sebastian Redl Jan 07 '15 at 15:55
  • 1
    The example you show with `Foo_Beta` is not partial specialization. Partial specialization would be e.g. `template class Foo { ... };` – Some programmer dude Jan 07 '15 at 15:55
  • @SebastianRedl: I suspected that may be the case. Mostly what I wanted was a clean "if you get Beta construct this way, Beth the other way, and it doesn't matter whether A is Alpha or Aleph." Aside from the constructor though, the class behaves the same for any combination A, B it will receive. – shavera Jan 07 '15 at 16:27

2 Answers2

4

You said:

template<typename A> Foo<A, Beta>::Foo(){/* some specialized construction */} //<- this doesn't work.

You can use that only if you specialize the entire class. You can't specialize just one member function of the class.

The following should work:

template<typename A> class Foo<A, Beta>
{
   Foo();
};

template<typename A> 
Foo<A, Beta>::Foo()
{
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
4

As mentioned by others - you cannot partially specialise a function. However, you can defer work in template functions to specialised implementation functions, which does give the effect of partial specialisation, for instance:

template<class X>
X make_a_B()
{
    return X();  // default implementation
}

template<>
Beta make_a_B<Beta>()
{
    Beta b;
    // do custom things with b...
    return b;  // fully specialised for Beta, everything else uses default case.
}

template<class X>
X make_an_A()
{
    return X();
}

template<typename A, typename B>
class Foo{
public:
    Foo()
    : _myA( make_an_A<A>() )
    , _myB( make_a_B<B>() )
    {}

    /*..*/
    A _myA;
    B _myB;
};

Foo<Alpha, Beta>() will now behave differently to Foo<Alpha, Gamma>()

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142