When running this:
template <typename T>
struct CodeByType
{
static const int32_t Value = 7;
};
template <>
struct CodeByType<int>
{
static const int32_t Value = 1;
};
template <typename Arg, typename... Args>
int32_t Sum()
{
// The compiler complains on this line
return Sum<Arg>() + Sum<Args...>();
}
template <typename Arg>
int32_t Sum()
{
return CodeByType<Arg>::Value;
}
int main()
{
auto sum = Sum<int, char, double>();
}
I'm getting:
Error C2668 'Sum': ambiguous call to overloaded function
Can someone please explain why and how to overcome it?
This looks awfully similar to the below code, which does compile, so I suppose it has something to do with Sum
not accepting any actual parameters.
template <typename T>
T adder(T first) {
return first;
}
template<typename T, typename... Args>
T adder(T first, Args... rest) {
return first + adder(rest...);
}
int main()
{
auto sum = adder(1, 7);
}
My memories of the template mechanism are old but if I recall correctly, their information is erased at a certain point in the compilation process.
My guess is that in the second case, the functions get distinguished not by the difference in the template types, but by the difference in the arguments.
In your case, you have no arguments, so stripped of the template information the two overloaded versions are equal and it cannot distinguish between them when you call it.
If you reduce your code to just:
You get a more helpful error message:
So it is clearer that there is an overload ambiguity between the first overload with
Args = <>
and the second one. Both are viable.One would might think as specialization for a solution:
which would indeed solve the issue, had it been allowed by the standard. Partial function specializations are not allowed.
C++17 solution:
This is the most elegant solution:
constexpr if to the rescue:
C++14 solution
We use SFINAE to enable/disable the function we want. Please note the function definition order had to be reversed.
C++11 solution
just replace
std::enable_if_t<>
withtypename std::enable_if<>::type
In c++17, it would simply be
In C++11, you may do: