問題のより良いサンプルについては、アップデートを参照してください。元のコードには、画像を混乱させる問題が混在しています。
この質問constexpr 関数内で非 constexpr 関数を呼び出すことができるのはなぜですか? 次のコードを提示しました
#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
許可します(ライブで参照してください)。
ただし、-fno-builtin
フラグを使用gcc
するとエラーが発生します (ライブで参照してください)。
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
そのため、組み込みバージョンの が定数式でseems
あると見なされます。ここではビルトインについて説明していますが、非 constexpr 関数のビルトインを定数式と見なすことができるこのケースについては説明していません。gcc
printf
gcc
これが実際に当てはまる場合:
- コンパイラはこれを行うことができますか?
- それらが許可されている場合、準拠していることを文書化する必要はありませんか?
- これは拡張機能と見なすことができますか?もしそうなら、C++ ドラフト標準セクションの
1.4
実装準拠の段落8にあるように、これには警告が必要なようです(強調鉱山):
適合する実装には、整形式プログラムの動作を変更しないという条件で、拡張機能 (追加のライブラリ関数を含む) が含まれる場合があります。実装は、この国際標準に従って不適切な形式の拡張機能を使用するプログラムを診断する必要があります。ただし、そうした後は、そのようなプログラムをコンパイルして実行できます。
アップデート
Casey が指摘しているように、元の問題にはいくつかのことが起こっており、それが悪い例になっています。簡単な例では、constexpr 関数ではないstd::powを使用します。
#include <cmath>
#include <cstdio>
constexpr double f()
{
return std::pow( 2.0, 2.0 ) ;
}
int main()
{
constexpr double x = f() ;
printf( "%f\n", x ) ;
}
警告やエラーなしでコンパイルおよびビルドしますが (ライブを参照)、追加-fno-builtin
するとエラーが発生します (ライブを参照)。注: C++11 で数学関数が constexpr でない理由:
error: call to non-constexpr function 'double pow(double, double)'
return std::pow( 2.0, 2.0 ) ;
^