13

次のコードがあります。

template <const char *p>
struct A{};

template <int i>
struct E{};

extern constexpr int i = 0;
constexpr float f = 0.f;
extern constexpr char c = 0;
int main(int argc, const char *argv[])
{
  A<&c> b; //works
  A<(const char *)(&i)> a; //Error: could not convert template argument ‘(const char*)(& i)’ to ‘const char*’
  E<(int)f> e; //works
  return 0;
}

なぜ行A<(const char *)(&i)> a;が間違っているのですか?-std=c++0x を指定して g++-4.6.1 でコンパイルしました。

編集:チャールズが定数式では許可されていないことを示唆しreinterpret_castたように、上記のコードを次のように変更します。

struct Base{};
struct Derived : public Base {};

template <const Base *p>
struct A{};

extern constexpr Base base = {};
extern constexpr Derived derived = {};
A<&base> a; //works
A<(const Base*)&derived> b; //error: could not convert template argument ‘(const Base*)(& derived)’ to ‘const Base*’

したがって、許可されていないだけreinterpret_castではありません。を使用A<static_cast<const base*>(&derived)すると、同じエラーが発生します。

@BЈовићへ:

  A<(const Base*)(0)> b; // error: could not convert template argument ‘0u’ to ‘const Base*’
4

1 に答える 1

4

「標準はそう言っている」という答えについては、コメントを見てください。

本当の問題は、なぜこれが許可されないのかということです。

テンプレート引数の型変換を断固として拒否することは非常に理にかなっています。なぜなら、本当に関心があるのはテンプレート引数の値だからです。ただし、型変換は任意に複雑になる可能性があり、強制的にconstexprs にする必要はありません。標準 (明らかに) は、組み込み (プリミティブ) 型の例外を作成しません。

E<(int)f>あなたの例もclang次の理由で反論されていることに注意してください。

エラー: 'int' 型の非型テンプレート引数は整数定数式ではありません

gcc がこれを許可する理由は疑わしいですが、constexpr明示的に宣言できる s を使用できると思います。のパラメータ リストでのアドレスをこっそり盗むことはできないことに注意してください。iA

于 2012-08-27T09:39:13.957 に答える