依存する型の名前解決
テンプレート定義内の修飾名で typename を使用して、指定した修飾名が型を識別することをコンパイラに通知します。 詳細については、「typename」を参照してください。
// template_name_resolution1.cpp
#include <stdio.h>
template <class T> class X
{
public:
void f(typename T::myType* mt) {}
};
class Yarg
{
public:
struct myType { };
};
int main()
{
X<Yarg> x;
x.f(new Yarg::myType());
printf("Name resolved by using typename keyword.");
}
出力
Name resolved by using typename keyword.
依存名の名前検索は、テンプレート定義のコンテキスト (次の例では、このコンテキストは myFunction(char) を検索) とテンプレートのインスタンス化のコンテキストの両方から名前を確認します。 次の例では、テンプレートは main でインスタンス化されるため、MyNamespace::myFunction はインスタンス化時点から参照可能となり、より適したものとして選択されます。 MyNamespace::myFunction の名前を変更した場合、myFunction(char) が代わりに呼び出されます。
すべての名前は依存名のように解決されます。 いずれにしても、名前の衝突が発生する可能性がある場合は、完全修飾名を使用することをお勧めします。
//template_name_resolution2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void myFunction(char)
{
cout << "Char myFunction" << endl;
}
template <class T> class Class1
{
public:
Class1(T i)
{
// If replaced with myFunction(1), myFunction(char)
// will be called
myFunction(i);
}
};
namespace MyNamespace
{
void myFunction(int)
{
cout << "Int MyNamespace::myFunction" << endl;
}
};
using namespace MyNamespace;
int main()
{
Class1<int>* c1 = new Class1<int>(100);
}
出力
Int MyNamespace::myFunction
テンプレートのあいまいさの解消
Visual Studio 2012 の Visual C++ は、template キーワードによるあいまいさの解消に関する C++ 98/03/11 規格の規則を強制します。 次の例では、Visual C++ 2010 は準拠していない行と準拠している行の両方を受け付けます。Visual Studio 2012 の Visual C++ は準拠している行のみを受け付けます。
#include <iostream>
#include <ostream>
#include <typeinfo>
using namespace std;
template <typename T> struct Allocator {
template <typename U> struct Rebind {
typedef Allocator<U> Other;
};
};
template <typename X, typename AY> struct Container {
#if defined(NONCONFORMANT)
typedef typename AY::Rebind<X>::Other AX; // nonconformant
#elif defined(CONFORMANT)
typedef typename AY::template Rebind<X>::Other AX; // conformant
#else
#error Define NONCONFORMANT or CONFORMANT.
#endif
};
int main() {
cout << typeid(Container<int, Allocator<float>>::AX).name() << endl;
}
あいまいさを解消する規則に準拠している必要があるのは、既定で、C++ は AY::Rebind がテンプレートでないと仮定し、そのためコンパイラは次の "<" を "より小さい" と解釈するためです。 "<" を山かっことして正しく解析できるように、Rebind がテンプレートであることを知っている必要があります。