为什么我可以在constexpr函数中调用非constexpr函数?

时间:2014-03-04 15:57:37

标签: c++ gcc c++11 constexpr side-effects

请考虑以下代码:

#include <stdio.h>

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

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

我原本希望编译器在printf内投诉f,因为f应该是constexpr,但是printf是不。为什么程序compile and print 15

1 个答案:

答案 0 :(得分:11)

该程序格式错误并且不需要根据C++11 draft standard部分7.1.5 constexpr说明符 5 <进行诊断/ em>其中说:

  

对于constexpr函数,如果不存在函数参数值   函数调用替换会产生一个常量   表达式(5.19),程序不正确;无需诊断。

并提供以下示例:

constexpr int f(bool b)
  { return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required

和第5.19 2 表示:

  

条件表达式是核心常量表达式,除非它   涉及以下之一作为潜在评估的子表达式   [...]

并包括:

  

- 调用除constexpr构造函数之外的函数   文字类或constexpr函数[注意:重载分辨率   (13.3)照常使用 - 后注];

在这种情况下我们可能更喜欢诊断,它可能只是一个疏忽,我有一个类似情况的错误报告gcc不会产生错误但我们可能会喜欢它:{{ 3}}。

更新

使用-fno-builtin标志会导致gcc生成以下错误:

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

所以gcc确实会考虑这个格式错误的,当它使用内置版本的printf时,它会忽略它。

虽然使用-pedantic稍微不一致会产生以下警告:

warning: ISO C++ forbids variable length array 'a' [-Wvla]
 char a[f()];
           ^

请注意,使用f()初始化 constexpr 变量:

constexpr int x = f() ;

会产生错误:

error: 'printf(((const char*)"a side effect!\012"))' is not a constant expression

另请注意,在更一般的情况下,不允许编译器将标准库函数标记为 constexpr Is the compiler allowed leeway in what it considers undefined behavior in a constant expression?