【问题标题】:implicit constexpr?隐式常量表达式?
【发布时间】:2013-03-22 21:41:55
【问题描述】:

C++11 编译器(他们是否)能注意到一个函数是一个 constexpr 并且即使它们没有被声明为 constexpr 也可以这样对待它们吗?

我正在使用直接来自 Wikipedia 的示例向某人演示 constexpr 的用法:

int get_five() {return 5;}

int some_value[get_five() + 7]; // Create an array of 12 integers. Ill-formed C++

令我惊讶的是,编译器可以接受它。因此,我进一步更改了 get_five() 以获取一些 int 参数,将它们相乘并返回结果,同时仍然没有被显式声明为 constexpr。编译器也可以。似乎如果编译器可以做到这一点,那么为了显式声明某些东西constexpr 所需的限制就没有多大意义了。

【问题讨论】:

  • 也许你的编译器支持 VLA 作为扩展。你考虑过吗?
  • 那是什么编译器?
  • 我正在使用我通过 MinGW-4.6.1 使用 g++,但也使用 -std=c++0x 和 -pedantic 开关。根据下面 JC 的回答,我目前正在考虑安装 Clang。 @Bo - 我说的是 constexpr 关键字,它(应该是)在上面的 get_five( ) 声明中是必需的。
  • @Arbalest - 据我所知,没有隐含的 constexpr,但正如 Jerry Coffin 在 g++ 以下的回答(取决于确切的选项集)可能允许在 C++ 中使用一些 C99 功能。跨度>

标签: c++ c++11 constexpr


【解决方案1】:

在正常运行的 C++11 编译器上,您的代码将被拒绝。

基于它被接受,您几乎可以肯定使用 gcc(或密切模仿其错误的东西)。 gcc [在某种程度上取决于标志] 可以接受在任何情况下都不是恒定的数组大小(例如,取决于用户的运行时输入),因为它们支持 C++ 中的 C99 可变长度数组的模拟。

【讨论】:

  • g++ 4.6.3、4.7.2 和 4.8 拒绝这个。至少在 liveworkspace 版本中
  • @icepack:是的,我相信你可以让它拒绝使用 VLA 的代码,如果你选择的话(但它默认接受 C++ 中的 VLA)。
  • @icepack 它在函数中时不会拒绝它:LWS - 它确实会发出警告!
  • 一定是这样。我通过 MinGW-4.6.1 使用 g++,但也使用 -std=c++0x 和 -pedantic 开关。
【解决方案2】:

编译器可以检测一个函数是否可以使用constexpr 声明,即使它们没有,出于优化目的(即计算编译时的函数)。编译器在 C++11 之前就是这样做的。

但在需要常量表达式的地方使用,例如整型模板参数,允许调用未使用constexpr关键字声明的函数是违反标准的。

【讨论】:

  • "编译器可以检测一个函数是否可以用 constexpr 声明" 你有任何参考来支持它吗?
  • @cseder 我很难想象任何现代编译器都不会这样做。这是关于编译器如何工作的基本知识。
  • 这几乎不是证据。当你说“现代编译器”时,我猜你排除了最新的 Visual C++ 2013 编译器,因为它不支持自动 memoization。 constexpr 只有在每次从 constexpr 函数返回的结果都相同的情况下才可用,因此不需要包含太多关于编译的知识。
  • 我从来没有说过任何关于记忆的事情。编译器还有其他方法可以生成常量表达式。
  • 我只是想知道你有什么事实来支持你的陈述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
相关资源
最近更新 更多