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