对不带参数的可变参数模板函数的模棱两可的调用? [英] Ambiguous call to variadic template function with no parameters?

查看:41
本文介绍了对不带参数的可变参数模板函数的模棱两可的调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行时:

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>();
}

我得到了:

错误C2668'Sum':对重载函数的模棱两可

Error C2668 'Sum': ambiguous call to overloaded function

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

Can someone please explain why and how to overcome it?

这看起来与下面的代码非常相似,它确实可以编译,因此我认为这与 Sum 不接受任何实际参数有关.

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);
}

推荐答案

如果将代码简化为:

Sum<int>();

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

You get a more helpful error message:

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.

因此,很显然,在 Args =<> 的第一个重载与第二个重载之间存在重载歧义.两者都是可行的.

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:

template <typename Arg>
int32_t Sum<Arg>()
{
    return CodeByType<Arg>::Value;
}

如果标准允许的话,这确实可以解决问题.不允许部分函数专门化.

which would indeed solve the issue, had it been allowed by the standard. Partial function specializations are not allowed.

这是最优雅的解决方案:

This is the most elegant solution:

constexpr if 进行救援:

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

C ++ 14解决方案

我们使用SFINAE启用/禁用所需的功能.请注意,功能定义顺序必须颠倒.

C++14 solution

We use SFINAE to enable/disable the function we want. Please note the function definition order had to be reversed.

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...>();

}

C ++ 11解决方案

只需将 std :: enable_if_t<> 替换为 typename std :: enable_if<> :: type

这篇关于对不带参数的可变参数模板函数的模棱两可的调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆