I've been beating my head against the wall for a day and a half, trying to learn template specialization and std::enable_if(). I'm not getting something. I'm trying to allow the specification of a return type from a class method, based on the class type AND user specification at compile time. For example, if the class type is integer, I might want a float return type (or an int) from the method.
My actual use case is an array for which I'm averaging all the values within. I might even want a boolean return value to reflect the outcome of a binary "vote". There are lots of combinations. There must be a way to do this without having the create all the overloads individually. My sample code is the simplest I could make it.
I'd be grateful for any pointers. How can I do this partial specialization, if indeed that is what it is called?
#include <string>
template <class T>
class Test {
public:
Test(T val) { val_ = val; }
template <typename U> U halve ();
private:
T val_;
};
template<class T> template<typename U>
U Test<T>::halve() {
throw std::invalid_argument("Cannot halve non-numeric objects");
}
template<class T> template<typename U> //example: T=int, U=float
typename std::enable_if_t<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value, U>
Test<T>::halve() { //error C2244 - unable to match function definition to an existing declaration
return ((U)val_ / (U)2);
}
int main() {
Test<int> t1(5);
float f = t1.halve<float>(); //expect 2.5
int i = t1.halve<int>(); //expect 2
Test<std::string> t2((std::string)"blah");
int t2h = t2.halve<int>(); //this will throw (by design)
return 0;
}