C ++:为什么这个constexpr不是编译时间常数

timmah2014

在以下C ++ 11代码中,对arraySize的最后一次调用导致编译错误。显然这是因为y是运行时大小的数组,并且无法为y推导出arraySize模板参数N。我不明白为什么x是一个编译时大小的数组,但是y最终是运行时大小的。arraySize模板函数直接取自Scott Meyers的“ Effective Modern C ++”项目1。

#include <cstddef>

template<typename T, std::size_t N>
constexpr std::size_t arraySize(T(&)[N]) noexcept { return N; }

struct S
{
    char c[10];
};

int main()
{
    S s;
    S* ps = &s;

    char x[arraySize(s.c)];
    char y[arraySize(ps->c)]; // why is y a runtime sized array?

    arraySize(x);
    arraySize(y); // error !?

    return 0;
}
本·沃格特

在C ++中,错误不是对的调用arraySize(y),而是y自身的声明

数组声明中的边界必须是“转换后的常量表达式”。

如果您的编译器接受的声明,y并且以后告诉您这y是运行时绑定的数组,则它不是C ++编译器。在任何已批准的C ++版本中,也没有当前运行时绑定的运行时数组。

之间的显著差arraySize(s.c)arraySize(ps->c)ps->c相同(*ps).c*引用操作需要在左值到右值转换ps,这不是一个常量表达式(也不是&s,见下文)。表达式的其余部分不涉及左值到右值的转换,数组左值直接由引用绑定。

常量表达式可以是glvalue核心常量表达式,其值指向作为常量表达式允许的结果(定义如下)的实体,或者是prvalue核心常量表达式,其值是对象,对于该对象及其子对象,其中:

  • 每个引用类型的非静态数据成员都引用一个实体,该实体是常量表达式的允许结果,并且

  • 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,该对象末尾的地址(5.7),函数的地址或空指针值。

如果实体是具有静态存储持续时间的对象,而该对象不是临时对象,或者是其值满足上述约束的临时对象,或者它是一个函数,则该实体是常量表达式的允许结果。

显然ps包含具有自动存储持续时间的对象的地址,因此无法声明它constexpr但是,如果您更改S s; S* ps = &s;static S s; constexpr S* ps = &s;

(另一方面,您会认为to的参数arraySize(s.c)也不是常量表达式,因为它是对静态存储持续时间的引用而不是对象)

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么null不为编译时间常数?

编译时间常数

在C ++中,是否可能使用带有和不带有编译时间常数的相同代码?

constexpr数组成员是否编译时间常数?

如果无法在MSVC上编译,为什么使用C ++ 17`constexpr这个模板化结构?

警告不是编译时间常数的函数参数

为什么C ++编译器的常数折叠效果更好?

C-为什么用&而不是switch / if比较常数?

对编译时间常数感到困惑

DataTestMethods的非编译时间常数

如果变量没有初始化,为什么这个 C 代码需要这么长时间来编译和执行?

为什么这个Objective-C ++程序不能编译?

为什么这个模板函数不能编译C ++

为什么这个常数表达式不是常数

为什么C ++编译需要这么长时间?

为什么这个C ++程序可以在MacOS上编译而不能在Ubuntu上编译?

Annotation参数必须是一个编译时间常数

最终变量与编译时间常数之间的差异

可以检查值是Rust中的编译时间常数吗?

@Import-注释参数必须是编译时间常数

具有编译时间常数的模板专业化

具有编译时间常数的模板化Lambda函数

为什么这个 C# 代码乱序执行?不是 ASYNC(至少我认为不是)

在constexpr函数中返回C字符串:为什么编译器没有警告?

为什么C ++编译器可以将函数声明为constexpr,而不能将其声明为constexpr?

尽管必需的头文件被注释掉,为什么这个 C++ 程序编译和运行?

为什么C#编译器会对这个嵌套的LINQ查询感到生气?

在 C 中,为什么这个语句 - 'i = 5i' 编译并将 'i' 设置为零?

为什么编译器将C程序汇编成这个?