After reading this question I had to realize once more how little I know about templates. I can understand, that a template specialization like this
// A
template <typename T> void foo(T x){}
template <> void foo<double>(int x){}
cannot work (error: template-id 'foo<double>' for 'void foo(int)' does not match any template declaration). Not only would it make little sense, but also parameter deduction would have no chance to get the right T. However, I do not understand why it does not work for return types:
// B
template <typename T> int foo(T x){}
template <> double foo<double>(double x){}
(similar error as above). Actually I dont have any particular use case at hand, but still I would be interested in how to choose a return type depending on T. As a workaround I found this:
// C
template <typename T> struct foo { static int moo(T x){return x;} };
template <> struct foo<double> { static double moo(double x){return x;} };
So it is possible to choose the return type depening on T. However, I am still puzzled...
What is the reason for B being not possible?
Even if strange, you may have
template <typename T>
void foo(int);
template <typename T>
char foo(int);
Demo
So your specialization would be ambiguous.
Actually, you can work around it either by using a template parameter for the return type or a traits class.
As an example:
#include<type_traits>
template<typename T>
T f() { return T{}; }
template<typename>
struct Traits;
template<>
struct Traits<int> {
using ReturnType = char;
};
template<>
struct Traits<char> {
using ReturnType = int;
};
template<typename T>
typename Traits<T>::ReturnType g() { return T{}; }
int main() {
static_assert(std::is_same<decltype(f<int>()), int>::value, "!");
static_assert(std::is_same<decltype(f<double>()), double>::value, "!");
static_assert(std::is_same<decltype(g<int>()), char>::value, "!");
static_assert(std::is_same<decltype(g<char>()), int>::value, "!");
}
In the case of g, if parameters are deduced you have that two apparently identical calls have different return types.
That said, specializations don't allow the user to change the declaration of a function.
That's why you have to play with such a definition to have different return types for different template arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With