1

ISO C 標準は、翻訳動作と実行動作を分離することについて重要な役割を果たしていることを知っています。これは、クロスコンパイラがすべてのターゲットの実行環境を実行する必要がないようにするためでもあります。

つまり、実行中のプログラムと比較して、コンパイラが利用できる情報が限られているということです。これにより、次のような関数からの戻り値に基づいて変数を初期化しないなど、ソース コードで実行できることが制限されます。

int twice (int val) { return val * 2; }
int xyzzy = twice (7);
int main () { printf ("%d\n", xyzzy); return 0; }

私が興味を持っているのは、C++11 のユーザー定義リテラルがこのスキームにどのように適合するかです。リテラル評価は関数に依存しているため、その関数が次のようなことを行うのを止めるにはどうすればよいですか:

  • 42_roughlyランダムな値を返しますか ( 40 から 44 の間の値を与えるなどの入力に基づいている場合でも)?
  • グローバル変数の変更などの副作用がありますか?

関数を呼び出さなければならないという事実は、これらがコンパイル時に計算されるという意味で実際にはリテラルではないことを意味しますか?

その場合、これらのリテラルが他の関数呼び出しよりも優れている点は何ですか。言い換えれば、その理由は次のとおりです。

int xyzzy = 1101_1110_b;

より好ましい:

int xyzzy = makeBin ("1101_1110");

?

4

1 に答える 1

6

その秘密は、ユーザー定義のリテラル関数を as として宣言するかどうかにありますconstexpr

これを比較してください(通常の実行時関数):

#include <iostream>
int operator "" _twice(unsigned long long num) { return num*2; }
int xyzzy = 7_twice;
int main () { std::cout << xyzzy << "\n"; return 0; }

これで(コンパイル時定数、static_assert作品):

#include <iostream>
constexpr int operator "" _twice(unsigned long long num) { return num*2; }
int xyzzy = 7_twice;
int main () {
    static_assert(7_twice == 14, "not compile time constant");
    std::cout << xyzzy << "\n";
    return 0;
}

明らかに、関数を宣言すると、そのconstexpr中のすべてのステートメントがconstexprコンパイル時の定数になるように制限されます。乱数の悪ふざけは許されません。

于 2013-06-21T05:19:35.600 に答える