IBMのWebサイトで見つけたこの例を考えてみましょう。
#include <iostream>
using namespace std;
void f(double) { cout << "Function f(double)" << endl; }
template<class T> void g(T a) {
f(123);
h(a);
}
void f(int) { cout << "Function f(int)" << endl; }
void h(double) { cout << "Function h(double)" << endl; }
void i() {
extern void h(int);
g<int>(234);
}
void h(int) { cout << "Function h(int)" << endl; }
int main(void) {
i();
}
何を印刷しますか?
私がこの例を採用したIBMのドキュメントは、ここから入手でき、次のように出力されます。
Function f(double) Function h(double)
これの理論的根拠は、テンプレートパラメータに依存する名前ルックアップがのインスタンス化の直前に実行される
i()
ため、は検出されますh(double)
が、は検出されないということh(int)
です。GCC 4.4.1を使用してコンパイルすると、次のように出力されます。
Function f(double) Function h(int)
GCCは、他のすべてがコンパイルされた後、テンプレート内のテンプレートパラメータに依存する名前を検索しているように見えるため、との両方
h(double)
を検出h(int)
し、後者を優先します。Clang 2.8を使用してコンパイルすると、コンパイルに失敗します。コンパイラエラーは次のとおりです。
ibm_example.cc:8:3: error: use of undeclared identifier 'h' h(a); ^ ibm_example.cc:16:3: note: in instantiation of function template specialization 'g<int>' requested here g<int>(234); ^ 1 error generated.
Clangは、テンプレートが宣言された時点でテンプレート内のテンプレートパラメータに依存する名前を検索しているように見えるため、どちら
h(double)
も検出されませんh(int)
。
どちらが正しいですか?