对没有参数的可变参数模板函数的模糊调用?

Shm*_*opy 4 c++ variadic-templates c++11

运行时:

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>();
}
Run Code Online (Sandbox Code Playgroud)

我越来越:

错误C2668'Sum':对重载函数的模糊调用

有人可以解释为什么以及如何克服它?

这看起来非常类似于下面的代码,它编译,所以我想它与Sum不接受任何实际参数有关.

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);
}
Run Code Online (Sandbox Code Playgroud)

bol*_*lov 6

如果您将代码简化为:

Sum<int>();
Run Code Online (Sandbox Code Playgroud)

您会收到更有用的错误消息:

31 : <source>:31:16: error: call to 'Sum' is ambiguous
    auto sum = Sum<int>();
               ^~~~~~~~
17 : <source>:17:9: note: candidate function [with Arg = int, Args = <>]
int32_t Sum()
        ^
24 : <source>:24:9: note: candidate function [with Arg = int]
int32_t Sum()
        ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

因此更清楚的是第一次重载与Args = <>第二次重载之间存在过载模糊.两者都是可行的.

人们可能会认为解决方案的专业化:

template <typename Arg>
int32_t Sum<Arg>()
{
    return CodeByType<Arg>::Value;
}
Run Code Online (Sandbox Code Playgroud)

如果标准允许,这确实可以解决问题.不允许使用部分功能.

C++ 17解决方案:

这是最优雅的解决方案:

constexpr如果要救援:

template <typename Arg, typename... Args>
int32_t Sum()
{
    if constexpr(sizeof...(Args) == 0)
      return CodeByType<Arg>::Value;
    else
      return Sum<Arg>() + Sum<Args...>();
}
Run Code Online (Sandbox Code Playgroud)

C++ 14解决方案

我们使用SFINAE来启用/禁用我们想要的功能.请注意,必须颠倒函数定义顺序.

template <typename Arg, typename... Args>
auto Sum() -> std::enable_if_t<(sizeof...(Args) == 0), int32_t>
{
      return CodeByType<Arg>::Value;
}


template <typename Arg, typename... Args>
auto Sum() -> std::enable_if_t<(sizeof...(Args) > 0), int32_t>
{
      return Sum<Arg>() + Sum<Args...>();

}
Run Code Online (Sandbox Code Playgroud)

C++ 11解决方案

只需更换std::enable_if_t<>typename std::enable_if<>::type