web-dev-qa-db-ja.com

__func __、__ FUNCTION__、および__PRETTY_FUNCTION__がプリプロセッサマクロではないのはなぜですか?

___func___、___FUNCTION___、および___PRETTY_FUNCTION___はプリプロセッサマクロとして扱われず、16.8定義済みマクロ名標準のセクション( N4527草案 )。

つまり、これらは フェーズ6 の文字列連結トリックでは使用できません。

_// Valid
constexpr char timestamp[]{__FILE__ " has been compiled: " __DATE__ " " __TIME__};
// Not valid!!!
template <typename T>
void die() { throw std::runtime_error{"Error detected in " __PRETTY_FUNCTION__}; }
_

私の知る限り、___FILE___、___DATE___、および___TIME___は、標準で述べられているように文字列リテラルに変換されます。

16.8定義済みマクロ名[cpp.predefined]

___DATE___

ソースファイルの翻訳日:a _"Mmm dd yyyy"_形式の文字列リテラル。月の名前は、asctime関数によって生成された名前と同じで、最初の文字of ddは、値が10未満の場合はスペース文字です。翻訳の日付が利用できない場合は、実装定義の有効な日付が提供されます。

___FILE___

現在のソースファイルの推定名(文字列リテラル)。

___TIME___

ソースファイルの変換時間:a-time関数によって生成された時間と同様に、フォーム__"hh:mm:ss"_の文字列リテラル。

___func___は、次の形式の関数ローカルの事前定義変数として標準で言及されています。

_static const char __func__[] = "function-name ";
_

つまり、これはローカル変数であるため、文字列連結のトリックは機能しません。

___FUNCTION___と___PRETTY_FUNCTION___については標準では言及されていませんが(実装は定義されていますか?)、___func___のように動作すると考えるのはかなり安全です。

したがって、問題は次のとおりです。なぜ___func___、___FUNCTION___および___PRETTY_FUNCTION___は関数ローカルの静的定数文字配列であるのに対し、___FILE___、___DATE___および___TIME___は文字列リテラルですか?この決定の背後にある理論的根拠(ある場合)は何ですか?

29
PaperBirdMaster

拡大する __func__前処理時に、プリプロセッサはどの関数を処理しているかを知る必要があります。解析はプリプロセッサがすでに行われた後で行われるため、プリプロセッサは通常それを知りません。

一部の実装は前処理と解析を組み合わせており、それらの実装では__func__思い通りに機能します。実際、私が正しく思い出せば、MSVCの__FUNCTION__はそのように機能します。しかし、翻訳のフェーズを分離する実装に対する不合理な要求です。

28
user743382