質問: std::vector]’: source_file.cpp:12:8: required from here source_file.cpp:6:21: error: dependent-name ‘C:: const_iterator’ is parsed as a non-type, but instantiation yields a type C::const_iterator *x; ^ source_file.cpp:6:21: note: say ‘typename C:: const_iterator’ if a type is meant ``` vc++: コンパイルが通る。 two-phase name lookup を行う gcc は実体化前に解析するのでエラーとなるが、MSVC は実体化された段階で解析するので、この時点では `C::const_iterator` は型と判明しているのでエラーにならない。 ### 参考文献 * Two phase name lookup for C++ templates - Why? - Stack Overflow * What exactly is "broken" with Microsoft Visual C++'s two-phase template instantiation? - Stack Overflow * C++ Team Blog | Two-phase name lookup support comes to MSVC * A Proposed New Template Compilation Model
回答: Two phase name lookup for C++ templates - Why? - Stack Overflow 上記に同様の質問がありました。そこによると、 > > * テンプレート内のシンボルを2つのカテゴリ(従属シンボルと非従属シンボル)に分類し、テンプレートの定義時に非依存シンボルを解決して、いくつかのローカル実装のシンボルに誤ってバインドされるリスクを減らす > * 依存シンボルに適切な場合は `typename` と `template` を指定するという要件と組み合わせることで、テンプレートがインスタンス化されたときだけではなく、テンプレートの定義時に解析とエラーチェックも可能になる(google翻訳) > > > とのことです。 最初の項目は、C++ Team Blog | Two-phase name lookup support comes to MSVCのリンクにもある、N0906 A Proposed New Template Compilation Modelにも書いてありました。 > > 理論的根拠:テンプレート作成者が以下の型を参照している場合 > > テンプレート定義の文脈では完全に知られている > > 彼が適用しようとしている操作を知っていると仮定し、 > > テンプレートユーザのコンテキストからの貢献はどれも > > 偶然です。 (google 翻訳) > > > 具体的な例も、C++ Team Blog | Two-phase name lookup support comes to MSVCにある通りです。次の場合、テンプレート定義の時点で、テンプレートを書いた人は既に知られている`func(void*)`を期待しているでしょう。しかし、Two-phase name lookup がない場合は`func(int)`に解決してしまいます。 ``` #include void func(void*) { std::puts("The call resolves to void*") ;} template void g(T x) { func(0); } void func(int) { std::puts("The call resolves to int"); } int main() { g(3.14); } ``` 出力: `The call resolves to void*`