首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Constant expressions

定义表达可以在编译时进行评估。

这类表达式可以用作非类型模板参数、数组大小,以及在需要常量表达式的其他上下文中使用,例如,

二次

代码语言:javascript
复制
int n = 1;
std::array<int, n> a1; // error, n is not a constant expression
const int cn = 2;
std::array<int, cn> a2; // OK, cn is a constant expression

二次

核心常数表达式

核心常数表达式是指在任何子表达式%28中有下列任何一个忽略未计算的表达式,例如sizeof或内建的右操作数。&&当左操作数计算为false29%。

1%29调用函数表达式,调用函数%28或未声明的构造函数%29司法官

二次

代码语言:javascript
复制
constexpr int n = std::numeric_limits<int>::max(); // OK, max() is constexpr
constexpr int m = std::time(NULL); // Error: std::time() is not constexpr

二次

2%29 a函数调用constexpr函数,该函数声明但未定义,或调用constexpr函数/构造函数模板实例化,其中实例化不能满足常数函数/构造函数要求。

3%29 a函数调用constexpr函数的参数,这些参数在替换时不会产生常量表达式。

二次

代码语言:javascript
复制
constexpr const int* addr(const int& ir) { return &ir; }
static const int x = 5;
constexpr const int* xp = addr(x); // OK
constexpr const int* tp = addr(5); // error: &5 is not a constant expression

二次

4%29 a函数调用constexpr构造函数,其参数在此函数调用的成员初始化程序列表中不生成常量表达式。

二次

代码语言:javascript
复制
int x;
struct A {
    constexpr A(bool b) : m(b?42:x) { }
    int m;
};
constexpr int v = A(true).m; // OK
constexpr int w = A(false).m; // error: non-const x

二次

5) A function call to a recursive constexpr function that would exceed compile-time recursion depth limit (implementation-defined)

(until C++14)

5) an expression that would exceed the implementation-defined limits

(since C++14)

6) The this pointer, except if used for class member access inside a non-static member function

(until C++14)

6) The this pointer, except in a constexpr function or a constexpr constructor that is being evaluated as part of the expression

(since C++14)

7%29一个表达式,其计算结果导致任何形式的核心语言未定义行为%28,包括有符号整数溢出、除以零、指针算法在数组边界外等等。是否检测到标准库未定义的行为未指定。

二次

代码语言:javascript
复制
constexpr double d1 = 2.0/1.0; // OK
constexpr double d2 = 2.0/0.0; // Error: not defined
constexpr int n = std::numeric_limits<int>::max() + 1; // Error: overflow
int x, y, z[30];
constexpr auto e1 = &y - &x; // Error: undefined
constexpr auto e2 = &z[20] - &z[3]; // OK
constexpr std::bitset<2> a; 
constexpr bool b = a[2]; // UB, but unspecified if detected

二次

8) A lambda expression

(until C++17)

9%29英镑隐式转换或修改%28,因为C++14%29应用于联合或者它的子物体

10%29任何其他的价值对价值隐式转换,除非那个...

%29具有整数或枚举类型,并引用完全非易失性Const对象,该对象使用常量表达式初始化。

二次

代码语言:javascript
复制
int main() {
    const std::size_t tabsize = 50;
    int tab[tabsize]; // OK: tabsize is a constant expression
 
    std::size_t n = 50;
    const std::size_t sz = n;
    int tab2[sz]; // error: sz is not a constant expression
                  // because sz is not initialized with a constant expression
}

二次

B%29是一个非易失性的glvalue,它引用字符串文字的一个元素。

C%29具有文字类型,并引用一个非易失性对象,该对象由constexpr或者它不可变的子对象。

d) has literal type and refers to a non-volatile temporary object, initialized with a constant expression

(until C++14)

d) has literal type and refers to a non-volatile object whose lifetime began within the evaluation of this expression

(since C++14)

11%29引用类型的变量或数据成员的id表达式.。除非它是用常量表达式初始化的,或者是临时对象的非静态数据成员,而临时对象是用常量表达式%28初始化的,直到C++14%29为止,否则它的生存期将在计算此表达式%28时开始,因为C++14%29。

12) conversion from cv void* to any pointer-to-object type

(since C++14)

13%29动态[医]铸造

14%29重释[医]铸造

15%29伪析构函数调用

16) an increment or a decrement operator

(until C++14)

16) modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression constexpr int incr(int& n) { return ++n; } constexpr int g(int k) { constexpr int x = incr(k); // error: incr(k) is not a core constant // expression because lifetime of k // began outside the expression incr(k) return x; } constexpr int h(int k) { int x = incr(k); // OK: x is not required to be initialized with a core // constant expression return x; } constexpr int y = h(1); // OK: initializes y with the value 2 // h(1) is a core constant expression because // the lifetime of k begins inside the expression h(1)

(since C++14)

17%29 a类型应用于多态类型的极值的表达式

18%29新表达式或删除表达式

19%29当结果未指定时,等于运算符或关系运算符。

20) an assignment or a compound assignment operator

(until C++14)

21%29次抛出表达式

22%29在lambda表达式中,引用this如果引用是ODR-Use,也可以定义在该lambda之外的变量。

二次

代码语言:javascript
复制
void g() {
  const int n=0;
  constexpr int j=*&n; // OK, outside of a lambda-expression
  [=]{ constexpr int i=n;  // OK, 'n' is not odr-used and not captured here.
       constexpr int j=*&n;// Ill-formed, '&n' would be an odr-use of 'n'.
     };
}

二次

note that if the ODR-use takes place in a function call to a closure, it does not refer to this or to an enclosing variable, since it accesses a closure's data member instead. // OK: 'v' & 'm' are odr-used but do not occur in a constant-expression // within the nested lambda auto monad = {return ={return v;};}; auto bind = {return ={return fvm(m());};}; // OK to have captures to automatic objects created during constant expression evaluation. static_assert(bind(monad(2))(monad)() == monad(2)());

(since C++17)

积分常数表达式

积分常数表达式一个整数或非作用域枚举类型的表达式,隐式转换为prvalue,其中转换的表达式是核心常量表达式。如果使用类类型的表达式(其中需要一个积分常量表达式),则表达式为上下文隐式转换到整数或非作用域枚举类型。只有积分常量表达式可以用作。

阵列界的维度新表达式除了第一个%28到C++14%29,位场长度,当基础类型不固定时,枚举初始化器,空指针常数%28,直到C++14%29,以及对齐。

转换常数表达式

转换常数表达式类型T是一个表达式隐式转换若要键入T,则转换表达式为常量表达式,而隐式转换序列仅包含:

  • 用户定义的转换%28,因此可以在期望积分类型为%29的情况下使用类。
  • lvalue-rvalue转换
  • 整体晋升
  • 非窄积分变换

array-to-pointer conversions function-to-pointer conversions function pointer conversions (pointer to noexcept function to pointer to function) qualification conversions null pointer conversions from std::nullptr_t null member pointer conversions from std::nullptr_t

(since C++17)

  • 数组到指针转换
  • 函数指针转换
  • 函数指针将%28指针转换为no,但函数指针转换为函数%29
  • 资格转换
  • 空指针转换std::nullptr_t
  • 的空成员指针转换std::nullptr_t

%28自C++17%29

  • 如果有的话参考绑定发生时,直接绑定%28而不是构造临时对象%29。只转换常数表达式可用作案例表达式,,,枚举数初始化器当基础类型固定时,阵列界的维度新表达式除第一%28自C++14%29外,并为整数和枚举%28,直到C++17%29非类型。模板参数...阿类型的上下文转换常量表达式bool是一种表达,上下文转换为bool,其中转换的表达式是常量表达式,而转换序列仅包含上面的转换。这些表达式可用于noexcept规格和静态断言声明...文字常量表达式文字常量表达式是一个prvalue核心常数表达式非指针文字类型%28的转换后,根据上下文%29的要求。数组或类类型的文字常量表达式要求每个子对象都用一个常量表达式初始化。参考常数表达式参考常数表达式是一个lvalue核心常量表达式,它指定具有静态存储持续时间或函数的对象。地址常量表达式地址常量表达式是类型的上下文%29所要求的转换后的prvalue核心常量表达式%28。std::nullptr_t或指向具有静态存储持续时间的对象的指针类型,或指向具有静态存储持续时间的数组结束后的对象,指向函数,或为空指针。注记实现不允许将库函数声明为conexpr,除非标准说明该函数在常量表达式中是强制性的。%28自C++14%29缺陷报告以下行为更改缺陷报告追溯应用于先前发布的C++标准。博士适用于公布的行为正确行为CWG 2167C++14评估的非成员引用(局部为评估)使评估成为非成员引用。允许非会员引用CWG 1313C++11允许未定义的行为,并禁止所有指针减法。相同数组指针减法确定,UB禁止。CWG 1952C++11标准库中未定义的行为需要进行诊断。未指定库UB是否被诊断另见
  • 常数说明符
  • std::is_literal_type
代码语言:txt
复制
 ? cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com