具有依赖类型的c ++ 11可变参数函数模板是否不明确?

鲍比·莫雷蒂

以下代码是递归可变参数函数重载的教科书示例。在clang和GCC中,它都会干净地编译,并main返回36(按预期):

template <typename T>
int add(T val)
{
    return val;
}

template <typename FirstTypeT, typename... RestT>
int add(FirstTypeT first_value, RestT... rest)
{
    return first_value + add<RestT...>(rest...);
}

int main(void)
{
    return add(12, 12, 12);
}

但是,这里稍作修改。它在模板定义中使用依赖类型,而不是直接使用template参数:

struct Foo
{
    using SomeType = int;
};

template <typename T>
int add(typename T::SomeType val)
{
    return val;
}

template <typename FirstT, typename... RestT>
int add(typename FirstT::SomeType first_value, typename RestT::SomeType... rest)
{
    return first_value + add<RestT...>(rest...);
}

int main(void)
{
    return add<Foo, Foo, Foo>(12, 12, 12);
}

它可以使用GCC 5.2进行编译和运行,但不能使用clang 3.8进行运行:

clang++ variadic.cpp -o var -std=c++11 -Wall
variadic.cpp:15:26: error: call to 'add' is ambiguous
    return first_value + add<RestT...>(rest...);
                         ^~~~~~~~~~~~~
variadic.cpp:15:26: note: in instantiation of function template specialization 'add<Foo, Foo>' requested here
    return first_value + add<RestT...>(rest...);
                         ^
variadic.cpp:20:12: note: in instantiation of function template specialization 'add<Foo, Foo, Foo>' requested here
    return add<Foo, Foo, Foo>(12, 12, 12);
           ^
variadic.cpp:7:5: note: candidate function [with T = Foo]
int add(typename T::SomeType val)
    ^
variadic.cpp:13:5: note: candidate function [with FirstT = Foo, RestT = <>]
int add(typename FirstT::SomeType first_value, typename RestT::SomeType... rest)
    ^
1 error generated.

我的问题是双重的。

  1. 是否真的有效地使用了参数包类型名模式,以将范围解析运算符应用于包中的每个成员,如中所示typename RestT::SomeType...
  2. 相对于标准而言,c是正确的,还是一个错误?第二个例子真的比第一个例子更含糊吗?(对于第一个示例,似乎您可以说单个参数重载与使用实例化的第二个参数不明确RestT = <>
哥伦布
  1. 是的,没关系。
  2. 当前的措词很清楚:部分排序期间完全忽略了参数包,因为没有参数([temp.deduct.partial] /(3.1))。[temp.func.order] / 5也给出了一个非常重要的例子,即使有可推论的模板参数也是如此-表明您的第一个例子也是模棱两可的:

    [注意:由于调用上下文中的部分排序仅考虑具有显式调用参数的参数,因此将忽略某些参数(即,函数参数包,带默认参数的参数和省略号参数)。[...] [示例

    template<class T, class... U> void f(T, U ...);  // #1
    template<class T            > void f(T       );  // #2
    
    void h(int i) {
      f(&i); // error: ambiguous
      // [...]
    }
    

    但是,这不是最佳的。关于可变参数模板部分排序,存在核心问题1395

    CWG同意应接受该示例,将这种情况视为迟来的决胜局,与参数pack相比首选省略的参数

    第1825期提供了更完善的策略。)两种编译器都在第一种情况下实现了此规则。只有GCC才做第二个(即可以认为是领先了半步)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

递归可变参数模板函数-不明确吗?

C ++ 11:可变参数模板函数参数的数量?

调用类内的函数的C ++ 11可变参数模板

通过可变参数模板的C ++ 11构造函数继承

C ++ 11可变参数模板函数存储

在C ++中可变参数模板中是否有对函数参数实施类型限制的好方法?

获取在C ++ 11中具有可变参数模板的函数的地址

传递给模板函数的两个lambda使参数的类型推导不明确-为什么?

c ++ 11递归可变参数模板

调用可变参数模板不明确

可变参数模板中的成员要求不明确

具有模板函数名称的可变参数模板

具有可变参数模板参数的函数指针

如何检查类型是否从模板函数中的某个可变参数模板类实例化?

javascript中带有函数参数的语法不明确

具有SFINAE的C ++ 11模板函数专业化允许进一步的专业化(错误:重载函数的调用不明确)

C ++ 11翻译可变参数模板以推断类类型

具有相同类型参数的可变参数模板化函数

具有相同类型的可变参数模板参数的构造函数无法编译

具有相同参数类型的可变参数模板函数

具有可变参数模板的成员函数指针

C ++中没有参数可变参数模板函数

在 C++20 中声明具有依赖类型参数的模板函数

是否可以构建具有不同类型的可变参数模板?

从具有可变参数模板构造函数的类型构造 std::function 对象

C ++:如何在可变参数模板参数上调用带有类型参数的函数?

调用可变参数函数模板时C ++ 11模棱两可的重载

如何具有类型和大小的可变参数模板?

可变参数模板函数参数和引用类型推导