NJ Aldea
NJ Aldea

Reputation: 53

Why does this explicit template specialization does not work?

from this code:

// Example program
#include <iostream>
#include <string>

struct Z { static const int z = 1; };
struct Y { static const int y = 2; };

template <typename A> struct TE { int foo(); int bar(); };

template <> int TE<Y>::bar() { return foo(); }
template <typename A> int TE<A>::bar() { return foo(); }

template <> int TE<Y>::foo() { return Y::y; }
template <typename A> int TE<A>::foo() { return A::z; }

template struct TE<Z>;
template struct TE<Y>;

int main()
{
    TE<Z> z;
    TE<Y> y;

    std::cout << z.bar() << std::endl;
    std::cout << y.bar() << std::endl;
    return 0;
}

with this error

21:28: error: specialization of 'int TE<A>::foo() [with A = Y]' after instantiation
 In instantiation of 'int TE<A>::foo() [with A = Y]':
13:12:   required from here
28:15: error: 'z' is not a member of 'Y'
 In member function 'int TE<A>::foo() [with A = Y]':
29:1: warning: control reaches end of non-void function [-Wreturn-type]

these implementations are done in separate cpp file. and the structs are in a header, typical explicit template instantiation.

why did this

int TE<Y>::bar() { return foo(); }

tries to use this

template <typename A> int TE<A>::foo() { return A::z; }

instead of this

template <> int TE<Y>::foo() { return Y::y; }

Upvotes: 1

Views: 716

Answers (2)

molbdnilo
molbdnilo

Reputation: 66371

The problem is that your foo specialization isn't known at the time bar is instantiated, so foo in both bars refers to the foo base template.

As the first error message says, when the compiler gets to your Y specialization, the base template has already been instantiated, using A = Y.
The second error is a "cascade error" due to the specialization failure, in the grand C++ tradition.

If you rearrange the definitions, it works:

template <typename A> int TE<A>::foo() { return A::z; }
template <> int TE<Y>::foo() { return Y::y; }

template <typename A> int TE<A>::bar() { return foo(); }
template <> int TE<Y>::bar() { return foo(); }

Upvotes: 1

danglingpointer
danglingpointer

Reputation: 712

http://en.cppreference.com/w/cpp/language/template_specialization

Explicit specialization can only appear in the same namespace as the primary template, and has to appear after the non-specialized template declaration.

Also, you need to follow the One-Definition-Rule (ODR). So usually you would provide your implementations along in the same header.

Upvotes: 2

Related Questions