自分でいくつかのテストを実行した後、これは MSVC のコンパイラ バグのようです。traits<T>::val
GCC では問題なく動作しますが、戻り値のテンプレート パラメーター内で使用しようとすると、MSVC は不可解で役に立たないコンパイラ エラー (質問のものと同じ) をS< E e >
返します。
面白いことに、S< E e >
代わりに整数を取るように変更すると、機能します。次の例を考えてみてください。これは、名前が異なるものと同じです。
enum E {
x
};
template <typename T>
struct traits {
static const E val = x;
};
template <E e>
struct S {
S(){};
};
template <typename T>
S< traits<T>::val > tricky(T t) {
return S< traits<T>::val > ();
};
int main() {
char thiskidwhowalksaround = 0;
S<x> s = tricky( thiskidwhowalksaround );
}
では、 1 つだけ変更してみましょう。
template <int e> // int instead of E
struct S {
S(){};
};
その後、プログラムは問題なくコンパイル (リンクおよび実行) されます。また、元に戻してから、値をE
直接渡すと、次のようになります。
template <typename T>
S< x > tricky(T t) {
// ^ here
return S< x > (); // <-- here
};
次に、プログラムはファイルをコンパイルします。MSVC には、次のことを行おうとすると失敗するという問題があります。
traits<T>::val
whereval
はあらゆる種類の列挙型です。これはコンパイラ自体の欠陥であると 99% 確信しています。これは完全に整形式の C++ のように見えるので、元のコード スニペットが機能することで、GCC が何か間違ったことや拡張機能を行っているとは言えません。したがって、私が収集できる最善のことは、MSVC は同業他社と比較してコンパイラの堅牢性に欠けているということです。
ここで読むのをやめてもかまいません。ここで、MSVC コンパイラについて怒鳴る時間をとります。
begin<rant>
VC++ チームが悪いとか C++ が悪いというわけではありませんが、私が収集したところによると、Microsoft のコンパイラ チームと標準ライブラリ チームは (執筆時点では)他の部門に比べて小規模です。このような基本的かつ重要な言語であり、MS 業界の中核の一部である言語が、比較的人員が少なく、私の短い人生の中で、世界で最も動きの遅い標準の 1 つであることに追いつくことができないことに腹を立てています。私は確かに VC++ チームで働いている個人をノックアウトしているわけではありませんが、C++ を高速化するだけでなく、コンパイラーを他のものと同じようにより良く機能させることに取り組んでいる人が増えていない理由について、私は非常に当惑しています。製品エリア。
end<rant>