11

ULL、などの事前定義されたリテラルfはコンパイル時に明らかに解決されるので、疑問に思います。標準(2.14.8 [lex.ext])はこれを定義していないようですが、実行時に向かう傾向があるようです。

[2.14.8 / 2]
ユーザー定義リテラルは、リテラル演算子またはリテラル演算子テンプレート(13.5.8)の呼び出しとして扱われます。ud-suffix Xを使用した特定のユーザー定義リテラルLに対するこの呼び出しの形式を判別するために、リテラルサフィックス識別子がXであるliteral-operator-idは、非修飾名ルックアップのルールを使用してLのコンテキストでルックアップされます( 3.4.1)。このルックアップで見つかった宣言のセットをSとします。Sは空であってはならない。
(私の強調。)

13.37fただし、私には、これは不要なランタイムオーバーヘッドをもたらすように思われます。リテラルは、または"hello"_x_xユーザー定義リテラルはどこにあるか)のように、コンパイル時に使用可能な値にのみ追加できるためです。
次に、テンプレート化されたuser-defined-literalを取得しました。これは、標準のAFAICSでは実際には定義されません(つまり、例は示されていません。間違っていることを証明してください)。その関数はコンパイル時に何らかの形で魔法のように呼び出されますか、それともまだ実行時ですか?

4

2 に答える 2

7

はい、関数呼び出しを受け取ります。constexprただし、リテラル演算子関数のため、関数呼び出しはコンパイル時の定数式になる可能性があります。

例については、これを参照してください。FDIS で許可されている高度な形式の計算を示す別の例として、constexprコンパイル時に base-26 リテラルを実行することができます。

typedef unsigned long long ull;

constexpr ull base26(char const *s, ull ps) {
  return (*s && !(*s >= 'a' && *s <= 'z')) ? throw "bad char!" :
    (!*s ? ps : base26(s + 1, (ps * 26ULL) + (*s - 'a')));
}

constexpr ull operator "" _26(char const *s, std::size_t len) {
  return base26(s, 0);
}

と言う"bcd-"_26と throw 式が評価されるため、戻り値が非定数になります。次に、"bcd-"_26定数式としての使用が不正になり、非定数の使用が実行時にスローされます。許可された形式"bcd"_26は、それぞれの計算値の定数式に評価されます。

文字列リテラルからの読み取りは FDIS によって明示的に許可されていませんが、問題はなく、GCC はこれをサポートしています (文字の左辺値参照は定数式であり、文字の値はコンパイル時に認識されます)。IMO、目を細めれば、あたかもこれが許可されているかのように FDIS を読むことができます。

次に、テンプレート化されたユーザー定義リテラルを取得しました。これは、標準の AFAICS で実際に定義されることはありません (つまり、例が示されていません。間違っていることを証明してください)。

リテラル演算子テンプレートを呼び出すリテラルの扱いは、2.14.8 で定義されています。13.5.8 には、リテラル演算子関数/関数テンプレート自体の詳細を示す他の例があります。

その関数は、コンパイル時に魔法のように呼び出されますか、それともまだ実行中ですか?

キーワードは関数呼び出し置換です。7.1.5 を参照してください。

于 2011-04-16T03:23:46.850 に答える
0

もちろん@Johannes Sは正しいですが、(私がこれに直面したので)明確に追加したいのですが、constexprユーザー定義のリテラルの場合でも、パラメーターは constexpr またはコンパイル時定数とは見なされませんテンプレートの整数定数として使用できます。

さらに、このようなものだけが実際にコンパイル時の評価を行います:

inline constexpr long long _xx(unsigned long long v) {
  return (v > 100 ) ? throw std::exception() : v; 
}
constexpr auto a= 150_xx;

したがって、それはコンパイルされません。しかし、これは:

cout << 150_xx << endl;

また、次のことは許可されていません。

inline constexpr long long _xx(unsigned long long v) {
  return some_trait<v>::value; 
}

これは面倒ですが、(他の) constexpr 関数を実行中にも呼び出すことができることを考えると当然です。

テンプレート形式を使用してコンパイル時の処理を強制できるのは、整数のユーザー定義リテラルの場合のみです。私の質問と自己回答の例: https://stackoverflow.com/a/13869688/1149664

于 2012-12-22T15:23:26.057 に答える