加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 05:19:52 所属栏目:百科 来源:网络整理
导读:在以下C 11代码中,最后一次调用arraySize会导致编译错误.显然这是因为y是一个运行时大小的数组,并且arraySize模板参数N不能被推导出来.我不明白为什么x是一个编译时间大小的数组,但是y结束运行时大小. arraySize模板函数直接从Scott Meyers的“有效现代C”项
在以下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 satis?es the above constraints,or it is a
function.

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读