Reputation: 1008
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 );
};
Upvotes: 2
Views: 145
Reputation: 208323
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;
};
Upvotes: 1