2021/06/14
コンパイラは、テンプレート関数のコンパイルを2段階に分けて行う。1回目はテンプレート引数に依存しない部分、2回目はテンプレート引数に依存する部分をコンパイルする。この仕様を two phase name lookup といい、C++03 から存在するルールである。
だが、MSVC は長い間 two phase name lookup をサポートしていなかった。そのため、以下のようなコードでコンパイルエラーが出なかった。本来は最初のフェーズ(テンプレート引数に依存しない部分)のエラーになるはず。
struct Base
{
void f() {}
};
template <typename T>
struct Derived : T
{
void g()
{
f(); // error C2065: 'f': 定義されていない識別子です。
T::f(); // OK
}
};
void foo()
{
Derived<Base> x;
}
これも同様にエラーにならなかった。
template <typename T>
struct X
{
template <typename TT>
void h() {}
};
template <typename T>
void foo()
{
X<T>::h<int>(); // error C7510: 'h': で依存する テンプレート の名前を使用するには、先頭に 'テンプレート' を付ける必要があります
X<T>::template h<int>(); // OK
}
このため MSVC では通るが clang ではエラーになる、というような状況だったが、最近になってようやく対応されたようだ。
/permissive- を指定すれば clang と同様にエラーになる。
