Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ gcc可以编译可变模板,而clang不能_C++_Templates_C++11_Gcc_Clang - Fatal编程技术网

C++ gcc可以编译可变模板,而clang不能

C++ gcc可以编译可变模板,而clang不能,c++,templates,c++11,gcc,clang,C++,Templates,C++11,Gcc,Clang,我正在看一些由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

我正在看一些由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...);
  }
};
struct Sum{
模板
静态T和(tn){
返回n;
}
模板
///静态T和(T n,参数…剩余){
静态自动求和(tn,Args…rest)->decltype(n+sum(rest…){
返回n+和(剩余…);
}
};
将此代码段用于
Sum::Sum(1,2.3,4,5);
clang-3.6(来自svn)时,无法使用
-std=c++11
/
-std=c++1y
编译此代码段,但gcc-4.9成功。当然,如果没有对返回类型进行类型推断,两个代码都可以编译,但这涉及类型转换,无法获得预期结果


那么这是否表明存在一个clang bug,或者是由于gcc扩展(关于c++11或c++14)?

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

1名称的声明点紧随其名称之后 完整声明人(第8条)及其初始值设定人(如有)之前, 除非下文另有说明

6在类成员声明点之后,可以 在其类的范围内被查找

以及§3.3.7[基本范围类别]/p1

以下规则描述了类中声明的名称的范围

1) 类中声明的名称的潜在作用域不仅包括 名称的声明点之后的声明性区域, 还有所有函数体,默认参数, 例外规范,以及 该类中的非静态数据成员(包括嵌套 课程)

后面的返回类型不在该列表中

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

因此,
sum
的变量版本不在其自身尾部返回类型的范围内,并且无法通过名称查找找到

在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...);
}
模板
结构和{
静态自动求和(tn,Args…rest)->decltype(n+sum::sum(rest…){
返回n+Sum::Sum(rest…);
}
};
模板
结构和{
静态T和(tn){返回n;}
};
模板
自动求和(tn,Args…rest)->decltype(sum::sum(n,rest…){
返回和::和(n,剩余…);
}

可能是一个叮当作响的错误,因为叮当声称支持所有C++11和所有C++14草稿功能。@dom0我也这么认为,但不知道草稿中在哪里以及如何解释这一点。虽然它没有回答您的问题,但这是相关的:这是,因此呈现的代码不是标准的,没有C++14返回类型推断,似乎没有o针对这一点的优雅解决方案,对吗?在我的脑海中,转发到模板类的非模板成员函数应该可以工作(
template auto sum(tn,Args…rest)->decltype(suminpl::impl(n,rest…){return suminpl::impl(n,rest…)}
,如果
summpl::impl
可以使用
summpl::impl
@HongxuChen查看我的编辑。我不知道这算不算优雅。
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...);
}