模板 – C:为什么这个constexpr不是编译时常数

前端之家收集整理的这篇文章主要介绍了模板 – C:为什么这个constexpr不是编译时常数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在以下C 11代码中,最后一次调用arraySize会导致编译错误.显然这是因为y是一个运行时大小的数组,并且arraySize模板参数N不能被推导出来.我不明白为什么x是一个编译时间大小的数组,但是y结束运行时大小. arraySize模板函数直接从Scott Meyers的“有效现代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(sc)和arraySize(ps-> c)之间的显着差异在于ps-> c与(* ps).c相同,* dereference操作符需要在ps上进行lvalue-to-rvalue转换,不是一个恒定的表达(也不是& s,见下文).表达式的其余部分不涉及到lvalue-to-rvalue转换,数组lvalue直接由引用绑定.

A constant expression is either a glvalue core constant expression whose value refers to an entity that is a permitted result of a constant expression (as defined below),or a prvalue core constant expression whose value is an object where,for that object and its subobjects:

  • each non-static data member of reference type refers to an entity that is a permitted result of a constant
    expression,and

  • if the object or subobject is of pointer type,it contains the address of an object with static storage duration,the address past the end of such an object (5.7),the address of a function,or a null pointer value.

An entity is a permitted result of a constant expression if it is an object with static storage duration that is either not a temporary object or is a temporary object whose value satisfies the above constraints,or it is a
function.

显然,ps包含具有自动存储持续时间的对象的地址,因此它不能被声明为constexpr.但是如果你改变S,一切都应该开始工作S * ps =& s;静态S; constexpr S * ps =& s;

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

猜你在找的C&C++相关文章