c++ - gcc 可以编译可变参数模板而 clang 不能

标签 c++ templates c++11 gcc clang

我正在阅读一些名为 An Overview of C++11 and C++14 的幻灯片由 Leor Zolman 先生介绍。在第 35 页,他介绍了一种使用 decltype 进行求和运算的方法。

struct Sum {
  template <typename T>
  static T sum(T n) {
    return n;
  }
  template <typename T, typename... Args>
  /// static T sum(T n, Args... rest) {
  static auto sum(T n, Args... rest) -> decltype(n + sum(rest...)) {
    return n + sum(rest...);
  }
};

当为 Sum::sum(1, 2.3, 4, 5); 使用此片段时,clang-3.6(来自 svn)无法使用 -std=c++ 进行编译11/-std=c++1y 但是 gcc-4.9 成功了。当然不对返回类型进行类型推导都可以编译,但是那涉及到类型转换,得不到预期的结果。

那么这是否表示一个 clang 错误,或者是因为 gcc 扩展(关于 c++11 或 c++14)?

最佳答案

Clang 的行为是正确的。这是一个 GCC 错误(演示文稿中的声明也不正确)。 §3.3.2 [basic.scope.pdecl]/p1,6:

1 The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below.

6 After the point of declaration of a class member, the member name can be looked up in the scope of its class.

§3.3.7 [basic.scope.class]/p1 说

The following rules describe the scope of names declared in classes.

1) The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies, default arguments, exception-specifications, and brace-or-equal-initializers of non-static data members in that class (including such things in nested classes).

trailing-return-types 不在该列表中。

尾随返回类型是声明符的一部分 (§8 [dcl.decl]/p4):

declarator:
    ptr-declarator
    noptr-declarator parameters-and-qualifiers trailing-return-type

因此 sum 的可变版本不在其自身的 trailing-return-type 范围内,无法通过名称查找找到。

在 C++14 中,只需使用实际的返回类型推导(并省略尾随返回类型)。在 C++11 中,您可以改用类模板和简单转发的函数模板:

template<class T, class... Args>
struct Sum {
    static auto sum(T n, Args... rest) -> decltype(n + Sum<Args...>::sum(rest...)) {
        return n + Sum<Args...>::sum(rest...);
    }
};

template<class T>
struct Sum<T>{
    static T sum(T n) { return n; }
};

template<class T, class... Args>
auto sum(T n, Args... rest) -> decltype(Sum<T, Args...>::sum(n, rest...)){
    return Sum<T, Args...>::sum(n, rest...);
}

关于c++ - gcc 可以编译可变参数模板而 clang 不能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26274207/

相关文章:

c++ - C++ 中的右值绑定(bind)混淆

C++11 正则表达式不匹配任何内容

c++ - 使用 stdio 和 C++/Python 处理 EOF 问题

c++ - 如果在多个共享库中调用并且启用了libstdc++静态链接,则C++流变得很糟糕

c++ - 为什么 C++ 数组的括号在变量上而不是在数据类型上?

c++ - 模板特化容器

c++ - 使用指针算法遍历同构 POD 结构

c++ - 将整数模板参数值映射到基本类型

c++ - 如何使用模板函数作为 Boost::Unit-test 的自定义谓词

c++ - 如何在函数内运行 Mersenne Twister?