この 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
うか?