模板 – 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直接由引用绑定.
显然,ps包含具有自动存储持续时间的对象的地址,因此它不能被声明为constexpr.但是如果你改变S,一切都应该开始工作S * ps =& s;静态S; constexpr S * ps =& s; (另一方面,你会认为arraySize(s.c)的参数也不是一个常量表达式,因为它是一个引用,而不是静态存储持续时间的对象) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |