Reputation:
I have a class template member function and I need to create a specialization that differs by the return type. But this is not allowed.
template<typename Type>
class Class {
Type Method(Type Argument) {...}
};
template <>
double Class<int>::Method(int Argument) {...}
Can you suggest a workaround ? (With the goal of hiding the templated definition for int
.)
Upvotes: 2
Views: 1471
Reputation: 170074
Let's discuss the root of the problem. When you specialize a member function for a class template, it causes the declaration of the class to be instantiated. So your specialized out-of-class definition conflicts with the generated declaration.
A possible solution would be to add a layer of indirection. Don't hard-code the return type as is, but make it depend indirectly on the template parameter, say from a traits class.
Something like this:
template<typename T>
struct ClassMethodReturn { typedef T type; };
template<>
struct ClassMethodReturn<int> { typedef double type; };
template<typename Type>
class Class {
typedef typename ClassMethodReturn<Type>::type ret_type;
ret_type Method(Type Argument) { return ret_type(); }
};
template <>
double Class<int>::Method(int Argument) { return 0.0; }
Thus you control the return type for each specialization rather easily.
Upvotes: 5
Reputation: 1212
Here is another workaround using std::enable_if
.
template<typename Type>
class Class {
public:
template <typename TypeDat=Type> std::enable_if_t<std::is_same<TypeDat,int>::value,double> Method(Type Argument) {
std::cout<<"case 1"<<std::endl;
}
template <typename TypeDat=Type> std::enable_if_t<!std::is_same<TypeDat,int>::value,Type> Method(Type Argument) {
std::cout<<"case 2"<<std::endl;
}
};
int main() {
Class<int> a;
a.Method(5); //print case 1
Class<char> b;
b.Method('c'); //print case 2
}
Personally, I love StoryTeller's solution.
Upvotes: 1