Namensauflösung für abhängige Typen
Verwenden Sie typename für qualifizierte Namen in den Vorlagendefinitionen, um dem Compiler mitzuteilen, dass der angegebene qualifizierte Name einen Typ identifiziert.Weitere Informationen finden Sie unter Typname.
// 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.");
}
Output
Name resolved by using typename keyword.
Namenssuche für abhängige Namen überprüft Namen von sowohl den Kontext der Vorlage Definition-im folgenden Beispiel, wird dieser Kontext myFunction(char)- und der Kontext der Vorlageninstanziierung suchen.Im folgenden Beispiel wird die Vorlage in main instanziiert; Daher ist MyNamespace::myFunction vom Punkt der Instanziierung sichtbar und wird als die bessere Übereinstimmung ausgewählt.Wenn MyNamespace::myFunction umbenannt wurde, wird stattdessen myFunction(char) aufgerufen.
Alle Namen werden aufgelöst, als ob sie abhängige Namen wären.Dennoch empfiehlt es sich, dass Sie vollqualifizierte Namen verwenden, wenn alle Konflikte gibt.
//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);
}
Output
Int MyNamespace::myFunction
Vorlagen-Disambigusierung
Visual C++ in Visual Studio 2012 erzwingt die Standardregeln für C++98/03/11 ermöglichen mit dem "Master " - Schlüsselwort.Im folgenden Beispiel wird Visual C++ 2010 die fehlerhaften Zeilen und die anpassenden Zeilen akzeptieren. Visual C++ in Visual Studio 2012 akzeptiert nur die anpassenden Zeilen.
#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;
}
Übereinstimmung mit den Disambigusierungsregeln ist erforderlich, da standardmäßig C++ ausgegangen wird, dass AY::Rebind keine Vorlage ist, sodass der Compiler folgenden "<" als weniger-als interpretiert. Sie muss wissen, dass Rebind eine Vorlage ist, sodass sie "<" als spitze Klammer ordnungsgemäß analysieren kann.