模板、数组和常量表达式
Templates, arrays and constant expressions
考虑以下代码:
template<char>
struct S { };
template<int N>
constexpr auto f(const char (&ref) [N]) {
return S<ref[0]>{};
}
int main() {
constexpr auto v = f("foo");
(void)v;
}
它不编译ref[0]
不是常量表达式
无论如何,下面的代码编译得很好:
template<int N>
constexpr auto f(const char (&ref) [N]) {
return ref[0];
}
int main() {
constexpr auto v = f("foo");
(void)v;
}
它们应该同时编译还是因为或多或少相同的原因而失败?
[expr。我们有:
条件表达式
e
是核心常数表达式,除非e
的求值[…]]将计算下列表达式之一:
[…]
- id表达式,指向引用类型的变量或数据成员,除非引用之前有初始化并且
-使用常量表达式或
初始化 -其生命周期开始于e
的评估;
无论如何,在这种情况下,它是用常量表达式初始化的,的生存期与e
相同,因此规则不适用。
我的推理有什么问题?
作为附带问题,我想问是否可以使用这样一个数组或它的一部分作为模板参数
This:
template<int N>
constexpr auto f(const char (&ref) [N]) {
return S<ref[0]>{};
}
是病态的,因为根据[temp.arg.nontype]:
非类型模板形参的模板实参必须是的转换常量表达式(5.20)模板参数的类型。
and from [expr.const]:
A 条件表达式 e是一个核心常量表达式,除非对e求值,遵循抽象机器(1.9)将计算下列表达式之一:[…]
的求值
(2.7) -左值到右值的转换(4.1),除非它应用于
(2.7.1) -指向完整的非易失性const的整型或枚举类型的非易失性glvalue对象,用常量表达式初始化,或
(2.7.2) -指向字符串字面值(2.13.5)的子对象或
的非易失性全局值(2.7.3) -一个非易失性的glvalue,它指向用constexpr定义的非易失性对象,或者指向该对象的不可变子对象,或
(2.7.4) -一个文字类型的非易失性全局值,它指向一个生命周期开始于
ref[0]
需要左值到右值的转换,并且这些子符号都不适用。注意,ref
不是字符串字面量,所以2.7.2不适用,它也不是用constexpr
定义的,因为它是一个函数参数,我们没有这个功能。
我们基本上需要将字符串字面值作为字面值传递的能力,这种能力目前还不存在。
另一个例子:
template<int N>
constexpr auto f(const char (&ref) [N]) {
return ref[0];
}
没有所需的转换常量表达式——该表达式是由模板非类型参数引入的。这段代码很好,只有当您试图用非constexpr
数组值初始化constexpr
变量时才会出现问题。
第一个示例不应该编译,因为您不能使用仅编译时的constexpr函数(或像D的__cfte
那样重载编译时)。
f
,它的返回类型是什么?至于旁边的问题:Boost Hana,尽管只支持最新的标准,只使用字符串文字运行时的东西,所以这可能是不可能的。
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 使用自动推导的 lambda 参数作为常量表达式
- 生成提升::hana::set 的常量表达式问题
- 为什么不能用常量表达式声明数组?
- 不是 lambda 函数中的常量表达式
- 函数调用在常量表达式中必须具有常量值
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 关于在需要常量表达式的上下文中使用的glvalue常量表达式的问题
- 生成 constexpr 字符串表,不能产生常量表达式
- 整体模板参数。错误:在常量表达式中使用'this'
- 如何在满足常量表达式的同时将整数传递给指针,传递给 std::array<double、integer>?
- 编译器错误:函数调用在常量表达式中必须有一个常量值
- 错误:'new'不能出现在常量表达式中
- 我可以写出小于 -0.5 两个 ulps 的常量表达式双精度吗?
- 编译器在传递 const 变量时返回错误:模板参数不是常量表达式
- 为什么我不能在非常量表达式上使用此模板阶乘函数?
- C++ 使用变量而不是常量表达式初始化数组
- 使用函数参数作为常量表达式的一部分 - gcc vs clang
- 片段着色器中的"错误:在 GLSL 1.30 及更高版本中禁止使用非常量表达式索引的采样器数组"