Question

This topic might exist, but the way in which one names this specific problem is confusing.

I have the following code - the first third is meant to be in an hpp file, second third in an impl file and last bit in a cpp. If I remove the commented out piece of code, it fails to compile for reasons I cannot understand.

Why does the compiler not complain about the other specializations I have, or alternatively - why does it not determine that line 45 is where my code is?

The errors:

test.cpp:45:23: error: no function template matches function template specialization 'foo'
int const A<int,int>::foo(int const & rhs) {
                  ^
test.cpp:58:5: error: call to 'foo' is ambiguous
    A<int, int>::foo( test_int );
    ^~~~~~~~~~~~~~~~
test.cpp:21:22: note: candidate function
    static int const foo(int const & rhs);
                 ^
test.cpp:45:23: note: candidate function
int const A<int,int>::foo(int const & rhs) {
                  ^
2 errors generated.

The code:

#include <iostream>

template <typename X, typename Y>
struct A {
    static X const foo(Y const & rhs);
};

template <typename X>
struct A<X,int> {
    static X const foo(int const & rhs);
};

template <typename Y>
struct A<int, Y> {
    static int const foo(Y const & rhs);
};


template <>
struct A<int,int> {
    static int const foo(int const & rhs);
};


//----------------------------------------

template <typename X, typename Y>
X const A<X,Y>::foo(Y const & rhs) {
    X ret;
    return ret;
};

template <typename X>
X const A<X,int>::foo(int const & rhs) {
    X ret;
    return ret;
};

template <typename Y>
int const A<int, Y>::foo(Y const & rhs) {
    return 42;
};

//If I uncomment the following line, the compiler barfs
//template <>
int const A<int,int>::foo(int const & rhs) {
   return rhs;
};




int main() {
    std::string test_str;
    int test_int;
    A<int,std::string>::foo( test_str );
    A<std::string,int>::foo( test_int );
    A<std::string,std::string>::foo( test_str );
    A<int, int>::foo( test_int );
};
Was it helpful?

Solution

A complete specialization is not a template, but a class. When you type:

template <>
int const A<int,int>::foo(int const & rhs) {
   return rhs;
};

The compiler sees that you want to specialize (template <>) a member function of a template A that takes two arguments. The member you are trying to specialize is for an specialization of the template where both arguments are int. The compiler tries to find the best match and cannot find it, since there are two equally good candidates: A<X,int> and A<int,Y> that could use that member function specialization. At that point it gives up.

Since what you want to provide is the definition of the member for A<int,int>, and that is a full specialization (no longer a template) you need to use the usual syntax: return type::member(args):

int const A<int,int>::foo(int const & rhs) {
   return rhs;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top