c++ - gcc是否将非常量表达式函数的内置函数视为常量表达式

标签 c++ gcc c++11 language-lawyer constant-expression

请查看更新以获得更好的问题示例。原始代码混合了一些问题,使图片变得困惑:

这个问题Why can I call a non-constexpr function inside a constexpr function?呈现如下代码

#include <stdio.h>

constexpr int f()
{
    return printf("a side effect!\n");
}

int main()
{
    char a[f()];
    printf("%zd\n", sizeof a);
}

我的回答是格式错误,但 gcc 4.8.2 允许它 ( see it live )。

但是,如果我们使用 -fno-builtin 标志 gcc 会产生一个错误 ( see it live ):

error: call to non-constexpr function 'int printf(const char*, ...)'
     return printf("a side effect!\n");
                                     ^

因此 似乎 gcc 正在将其内置版本的 printf 视为常量表达式。 海湾合作委员会 documents builtins here但没有记录可以将非 constexpr 函数的内置函数视为常量表达式的情况。

如果确实是这样的话:

  • 是否允许编译器执行此操作?
  • 如果他们被允许,他们是否必须将其记录下来才能符合要求?
  • 这可以被认为是一个扩展吗,如果是的话,这似乎需要一个警告,因为 C++ draft standard 1.4 实现合规性8 说(强调我的):

A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

更新

正如 Casey 指出的那样,原始问题中发生了一些事情,这使得它成为一个糟糕的例子。一个简单的例子是使用 std::pow这不是一个 constexpr 函数:

#include <cmath>
#include <cstdio>

constexpr double f()
{
    return std::pow( 2.0, 2.0 ) ;
}

int main()
{
    constexpr double x = f() ;

    printf( "%f\n", x ) ;
}

编译和构建时没有警告或错误 ( see it live ) 但添加 -fno-builtin 会生成错误 ( see it live em>).注:why math functions are not constexpr in C++11 :

error: call to non-constexpr function 'double pow(double, double)'
     return std::pow( 2.0, 2.0 ) ;
                               ^

最佳答案

是的,gcc 正在考虑一些 builtin functions作为 constexpr 即使标准没有明确标记它们。我们可以在 gcc 错误报告 [C++0x] sinh vs asinh vs constexpr 中找到专门针对 cmath 中的数学函数的讨论。其中说:

LWG 2013 does seem to allow GCC to treat these functions as constexpr. So, fixed for 4.7

指的是 LWG issue 2013其最初提议的决议是将以下内容添加到 17.6.5.6 [constexpr.functions] 部分(强调我的前进):

[...]Additionally, an implementation may declare any function to be constexpr if that function's definition satisfies the necessary constraints[...]

但在 C++11 之后,决议被颠倒了,最终的决议是:

[...]An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.[..]

所以这是当前(在 C++14 中)a explicitly non-conforming extension据我所知,这在 C++11 中是不符合规范的,因为它改变了可观察到的行为,因此不允许通过as-if 规则

Jonathan Wakely 指出了一个libstdc++ 邮件列表讨论:PR libstdc++/49813 revisited: constexpr on functions (and builtins)由于上述问题,讨论了重新打开上述错误报告的地方:

I believe we should re-open the bug in light of the actual resolution of LWG 2013 (adding constexpr is forbidden).

The FE should not treat builtins as constexpr in strict-conformance mode.

We should either remove _GLIBCXX_CONSTEXPR from <cmath> entirely or make it conditional on __STRICT_ANSI__.

关于c++ - gcc是否将非常量表达式函数的内置函数视为常量表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22182432/

相关文章:

c++ - 如何一次将多个值分配给一个结构体?

c++ - C++验证数字输入中的逗号位置

c++ - 在Linux中以最低延迟从多播套接字接收数据

c++ - 如何接受 boost::asio::ssl::stream<boost::asio::ip::tcp::socket> 作为 boost::asio::ip::tcp::socket 类型的参数

c++ - 不同编译器的 C++ 类型的大小

c++ - 阻止编译器优化的多态性示例?

c++ - 静态 constexpr 成员似乎不支持 std::min

C 编程 : Recursion

c++ - 在不同线程中调用 std::function

c++ - 为什么 std::swap 不适用于 std::bitset<n> 内容?