12

問題のより良いサンプルについては、アップデートを参照してください。元のコードには、画像を混乱させる問題が混在しています

この質問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 関数のビルトインを定数式と見なすことができるこのケースについては説明していません。gccprintfgcc

これが実際に当てはまる場合:

  • コンパイラはこれを行うことができますか?
  • それらが許可されている場合、準拠していることを文書化する必要はありませんか?
  • これは拡張機能と見なすことができますか?もしそうなら、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 ) ;
                               ^
4

2 に答える 2

6

はい、標準で明示的にマークされていなくても、gcc一部の組み込み関数constexprと見なしています。バグ レポート[C++0x] sinh vs asinh vs constexprcmathにある数学関数に特に関連する議論を見つけることができます。gcc

LWG 2013 では、GCC がこれらの関数を constexpr として扱うことを許可しているようです。そのため、4.7 で修正されました

これは、LWG issue 2013を参照しており、最初に提案された解決策は、セクション17.6.5.6 [constexpr.functions]に以下を追加することでした(今後の強調):

[...]さらに、関数の定義が必要な制約を満たしている場合、実装は任意の関数を constexpr として宣言できます[...]

しかし、C++11 以降では解像度が逆になり、最終的な解像度は次のようになりました。

[...]実装は、明示的に必要とされる場合を除き、標準ライブラリ関数の署名を constexpr として宣言してはなりません。[..]

したがって、これは現在(C++ 14では明示的に非準拠の拡張であり、観察可能な動作を変更するため、C ++ 11ではこれが非準拠であると私が知る限り、as-if経由では許可されませんルール

libstdc++Jonathan Wakely は、メーリング リストでの議論を指摘しています: PR libstdc++/49813 revisited: constexpr on functions (and builtins) 上記の問題により、上記のバグ レポートを再度開くことが議論されました。

LWG 2013 (constexpr の追加は禁止されています) の実際の解決に照らして、バグを再度オープンする必要があると思います。

FE は、厳密準拠モードでビルトインを constexpr として扱うべきではありません。

<cmath> から _GLIBCXX_CONSTEXPR を完全に削除するか、__STRICT_ANSI__ の条件付きにする必要があります。

于 2015-01-12T16:51:17.693 に答える