在constexpr中使用argc,是否严格要求所涉及的任何子表达式都是常量表达式
Using argc in a constexpr, is it strictly required that any sub-expression involved be a constant expression?
示例:
int main(int argc, char**)
{
constexpr int a = argc * 0;
(void)a;
constexpr int b = argc - argc;
(void)b;
return 0;
}
argc
不是一个常量表达式,但编译器仍然能够在编译时(即0
(计算a
和b
的结果。
g++接受上面的代码,而clang和MSVC14拒绝它。
标准是否允许编译器在constexpr
方面像g++一样智能?
argc * 0
和argc - argc
都不是常量表达式,在某些情况下允许左值到右值的转换,它们都不适用于此处。如果我们看一下C++11标准部分5.19
[expr.const]的草案,它列出了例外情况。上面写着:
条件表达式是核心常量表达式,除非它包含以下其中一个作为潜在的已评估子表达式[…]
并且有几个项目符号,包括以下关于左值到右值转换的项目符号:
左值到右值的转换(4.1(,除非它应用于
整型或枚举类型的glvalue,引用前面带有的非易失性常量对象初始化,用常量表达式或初始化
文字类型的glvalue,引用用constexpr定义的非易失性对象,或引用到这样一个对象的子对象,或者
文字类型的glvalue,它引用了一个非易失性临时对象,该对象的生存期尚未结束,用常量表达式初始化;
值得注意的是,gcc不接受以下代码(请参阅直播(:
constexpr int a = argc * 2;
因此,看起来gcc是在说我知道结果将为零,因此它执行常数折叠,并且不需要执行argc
的左值到右值转换来确定结果。
不幸的是,我在5.19
节中没有看到任何允许这种短路的规定。这看起来和int a=1的情况非常相似,a||1是常量表达式吗?它有一个错误报告,但gcc团队没有人回复。我在错误报告中添加了一条注释,表明这似乎是相关的。
Mark在下面的评论表明这是一个错误:
一些gcc开发人员正在研究一个完整的c++延迟折叠分支,这将延迟一些优化,并可能解决这个问题。由于其他原因,拒绝这个问题中的代码是非常低优先级的,这一点很重要
常量表达式是否严格要求每个子表达式都是常量表达式?不,例如5.19
中说:(emphasis mine(
条件表达式是核心常量表达式,除非它包含以下其中一个作为潜在的求值的子表达式(3.2(,,但逻辑AND(5.14(、逻辑OR(5.15(和条件的子表达式(5.16(未经评估的操作不被视为[…]
因此以下是一个常量表达式:
constexpr int a = false && argc * 0;
因为CCD_ 13从左到右评估短路,所以不评估CCD_。
您可以在这里查看:cppreference.com 上的constexpr
基线是constexpr应该是在编译时可以明确确定的东西,这样编译器就可以在计算表达式时替换它的值。
我认为问题在于argc不是constexpr。编译器不知道。事实上,您可以使用不同数量的参数来执行main。如果gcc接受它,它可能是一个bug,或者可能有一些我不明白的微妙之处。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- (C++)分析树以计算返回错误值的简单算术表达式
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 提升精神:解析布尔表达式并简化为规范范式
- 正则表达式以匹配数字的重复模式,后跟任何类型的分隔符?
- 标准库中的任何正则表达式语法是否支持 (?(定义)用于子模式参考?
- 适用于 gcc 4.8 的任何正则表达式库
- 我的 Boost 正则表达式与任何内容都不匹配
- 将任何类型的表达式放在 c++ 的初始化列表中在语法上是否正确?
- 如何为字符串编写正则表达式,其中包含一个数字至少一个数字,并且不包含任何字母
- 是否有任何合理的场景,程序员可能希望避免布尔表达式的短路计算
- 'for'的增量表达式没有任何效果
- C++11正则表达式不匹配任何内容
- 正则表达式以匹配任何行上的多个 MBCS 字符串
- C++中的Regex,从正则表达式中获取文本任何部分的字符串
- 在constexpr中使用argc,是否严格要求所涉及的任何子表达式都是常量表达式
- 是否有任何C/ c++编辑器支持替换正则表达式?
- 由于抽象模板arg的实例化,Boost::lambda表达式编译失败.任何解释和/或解决方法
- 正则表达式与从 C++ 中的文件加载的长字符串的任何内容都不匹配
- 是否可以将任何类对象作为测试表达式传递给任何测试表达式,例如if,while like ifstream对象