C++ gcc可以编译可变模板,而clang不能
我正在看一些由Leor Zolman先生介绍的幻灯片。在第35页,他介绍了一种使用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
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...);
}