6

C++11 では、次の形式の前処理ディレクティブが...

#if expr

...が検出され、で説明されているように としてexpr評価されます。constant-expression16.1 [cpp.cond]

これは のマクロ置換の後に行われexpr、その識別子 (およびキーワード) は 0 に置き換えられ、preprocessing-tokensに変換されtokensdefined演算子が評価されます。

私の質問は、トークンの 1 つexpruser-defined-literal?

exprユーザー定義のリテラルは関数呼び出しのようなものですが、識別子置換の副作用として、関数呼び出しは (私が思うに) では発生しません。ただし、技術的user-defined-literalsには生き残ることができます。

エラーだと思いますが、標準からそれを結論付ける方法がよくわかりませんか?

おそらく、第 16 節にユーザー定義リテラルを追加することの (衒学的な) 影響[cpp]は単に無視されたのでしょうか?

または、何か不足していますか?

アップデート:

例で明確にするには:

この前処理は次のことを行います。

#if 123_foo + 5.5 > 100
bar
#else
baz
#endif

bar または baz またはエラーですか?

GCC 4.7 レポート:

test.cpp:1:5: error: user-defined literal in preprocessor expression

したがって、エラーと見なされます。これは、標準を参照して正当化できますか? それともこれは単に「暗黙的」ですか?

4

2 に答える 2

3

C++11 では、... の形式の前処理ディレクティブが検出されると、で説明されているように として評価され#if expr ...ます 。exprconstant-expression16.1 [cpp.cond]

これは のマクロ置換の後に行われexpr、その識別子 (およびキーワード) は に置き換えられ0、 にpreprocessing-tokens変換されtokensdefined演算子が評価されます。

tokens私の質問は、 inの 1 つexpruser-defined-literal?の場合はどうなるかということです。

プログラムの形式が正しくありません。

16.1/1私の議論の核心は、脚注の所見から得られます。147翻訳フェーズ 4 ではidentifiers、マクロ名以外はまだありません。

口論:

によると2.14.8 [lex.ext]/2

Aは、 またはuser-defined-literalの呼び出しとして扱われます。literal operatorliteral operator template (13.5.8)

したがって、ここでは、 で説明されているすべての置換の後でも、(演算子) 関数への呼び出しが残っています16.1/4。(関数を使用するなどの他の試みは、constexprすべての非マクロを に置き換えることによって阻止さidentifiers0ます。)

これは変換フェーズ 4 で発生するため、関数はまだ定義も宣言もされていません。mustのルックアップの試みliteral-operator-idは失敗します (16.1/1同様の引数については脚注 147 を参照してください)。

少し別の角度から見ると、次の5.19/2ことがわかります。

Aconditional-expressioncore constant expression、潜在的に評価される部分式 (3.2) [...] として次のいずれかを含まない限り、 です。

  • [...]
  • リテラル クラスまたは constexpr 関数の constexpr コンストラクター以外の関数の呼び出し。
  • 未定義の constexpr 関数または未定義の constexpr コンストラクターの呼び出し [...];

このことから、 auser-defined literalで a を使用するには、定義済みconstexprconstant expressionが必要ですが、これも翻訳フェーズ 4 では使用できません。 literal operator

gcc がこれを拒否するのは正しいことです。

于 2013-02-17T12:03:12.987 に答える
0

C++11 では、フォームの前処理ディレクティブが検出されると、16.1 で説明されているように定数式として評価されます#ifdef exprexprこれは expr のマクロ置換の後に行われ、その識別子 (およびキーワード) は 0 に置き換えられ、その前処理トークンはトークンに変換され、定義された演算子が評価されます。

いいえ!

#ifdef#ifndef、またはの引数definedは評価されません。たとえば#define、プリプロセッサ シンボルを使用したことがないとしますSYMBOL_THAT_IS_NEVER_DEFINED。これは完全に有効です:

#ifdef SYMBOL_THAT_IS_NEVER_DEFINED
code
#endif

シンボルが定義されていないシンボルを展開することは違法です。SYMBOL_THAT_IS_NEVER_DEFINEDが定義されていないと仮定すると、これは違法です。

#if SYMBOL_THAT_IS_NEVER_DEFINED
code
#endif

逆参照する前にポインターが null でないかどうかをチェックするのと同様に、使用する前にシンボルが定義されているかどうかをチェックすることは正当です。

#if (defined SYMBOL_THAT_MIGHT_BE_DEFINED) && SYMBOL_THAT_MIGHT_BE_DEFINED
code
#endif
于 2013-02-16T23:13:30.063 に答える