23

この SO の質問に答えると、標準 (既に C++03、まだ C++11) で、アドレスが形式& id-expression(およびいくつかの例外)である場合にのみ、非型テンプレート引数としてアドレスを使用できることがわかりました。

しかし、なぜそうなのかは答えられませんでした。

14.3.2 テンプレートの非型引数 [temp.arg.nontype]

非型、非テンプレートのテンプレート パラメータのテンプレート引数は、次のいずれかになります。

[...]

— 静的ストレージ > 期間および外部リンケージまたは内部リンケージを持つオブジェクトのアドレスを指定する定数式 (5.19)、または外部リンケージまたは内部リンケージを持つ関数 (関数テンプレートおよび関数テンプレート ID を含むが、非静的クラス メンバーを除く) を表す定数式 (5.19) (括弧を無視して) & id-expressionと同じですが、名前が関数または配列を参照する場合は & を省略でき、対応するテンプレート パラメーターが参照の場合は省略されます。[...]

(n3485、地雷強調)

例:

using TFoobar = int (*)();
template < TFoobar tp > struct foo_struct{};

int foobar() { return 42; }
constexpr TFoobar pFoobar = &foobar;

foo_struct < &foobar > o0; // fine
foo_struct < pFoobar > o1; // ill-formed

翻訳フェーズに関係があると思います。つまり、コンパイラはアドレスについてあまり知りません。それなのに、どうして許されないの?コンパイラがマクロ置換に似たものを使用して を置き換えることは可能ではないpFoobarでしょ&foobarうか?

4

2 に答える 2

2

クラスFoo<&X>とを考えてみましょう。Foo<&Y>両方とも静的メンバーint Barです。Barリンカは、プログラムに 1 つまたは 2 つのオブジェクトがあるかどうかを判断できなければなりません。&Xここで、リンカーは、およびに値を割り当てる可能性が最も高い当事者でもあると考えて&Yください。

スタンダードをもう一度見てみましょう。書かれているように、コンパイラは実際のアドレスをリンカに伝える必要はありません。代わりに、id-expression. リンカーはid-expression、数値アドレスを割り当てる前であっても、2 つの が同じであるかどうかを判断する能力をすでに備えています。

于 2013-04-08T20:30:19.737 に答える
0
  1. 変数は実行時にのみ設定されるため、変数にすることはできません。
  2. コンパイル時にアドレスconstexprを知ることができないため、これを にすることはできません。ほとんどの場合、実行前の再配置後にのみ修正されます。
  3. 理論的には算術式である可能性がありますが (標準では許可されていません)、配列要素のアドレスの一般的なケースでは、&arr[i]代わりにarr + i.
于 2013-04-08T20:30:54.987 に答える