0

I am trying to write a class that has some partial and explicit specialization. Having trouble with name lookup quirks though. Right now I have:

template <typename C, typename R>
class Command {
public:
    Command();

private:
void doTheDew() {
    /* ... */
}
};

template <typename C, typename R>
Command<C, R>::Command() {
    doTheDew();
}

template<typename R>
class Command<void, R> {
public:
    Command() {
        this->doTheDew();
    }
};

template<typename C>
class Command<C, void> {
public:
    Command() {
        this->doTheDew();
    }
};

template<>
class Command<void, void> {
public:
    Command() {
        this->doTheDew(); // 1
    }
};

On the line marked with "1" I get the error

class Command<void, void> has no member named doTheDew

I've tried quite a bit at this point and don't understand what I'm missing.

  • 2
    Each partial-specialization is its own class. You need to provide the respective definitions of `doTheDew` – David G Jan 13 '14 at 21:28
  • Maybe I'm messing up terminology but the partial-specialization seem to work (I need the this dereference otherwise I got a name lookup error). It's only the explicit specialization that I'm having problems with. – NotGoodWithComputer Jan 13 '14 at 21:33

2 Answers2

1

It fails immediately in the line marked // 1, but it also fails when instantiated in both of the other specializations.

Command<int,void> c1; // fail
Command<void,int> c2; // fail
Command<int,int> c3; // OK

Live example

The reason is that none of the specialization has a doTheDew() method, as each specialization is its own class with its own members.

You might consider moving methods which should be available for the primary template and all the specializations to a base class. Don't forget to derive both the primary template and the specialization from that base then.

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
1

As 0x499602D2 pointed out, templates are only that, templates to generate classes. So each template specialization is a different class. You need to provide the doTheDew declaration/definition in all of the specializations.

One way to reduce code duplication is to create a base class which provides the doTheDew method, and make all speciallizations inherit from it:

struct dothedew_impl
{
    void doTheDew();
};

template<typename C>
class Command<C, void> : public dothedew_impl
{
public:
    Command() {
        this->doTheDew();
    }
};

Of course if the doTheDew() method depends on some template parameter of the class, you could make the base class a template too:

template<typename T>
struct dothedew_impl
{
    void doTheDew();
};

template<typename C>
class Command<C, void> : public dothedew_impl<C>
{
public:
    Command() {
        this->doTheDew();
    }
};

Note that the this-> in the last Command() implementation example is necessary, because template dependent names are resolved during second template parsing phase. The this-> is used to force the compiler to include doTheDev() into the class scope, and move it to the first phase.

Community
  • 1
  • 1
Manu343726
  • 13,969
  • 4
  • 40
  • 75