Namensauflösung für abhängige Typen

Wird typename für qualifizierte Namen in Vorlagendefinitionen verwendet, um dem Compiler mitzuteilen, dass der angegebene qualifizierte Name einen Typ identifiziert. Weitere Informationen finden Sie unter "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.

Die Namenssuche nach abhängigen Namen untersucht Namen aus dem Kontext der Vorlagendefinition – im folgenden Beispiel würde dieser Kontext finden myFunction(char)– und den Kontext der Vorlageninstanziierung. Im folgenden Beispiel wird die Vorlage in Standard instanziiert. Daher ist die MyNamespace::myFunction Vorlage vom Instanziierungspunkt sichtbar und wird als 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 wird empfohlen, vollqualifizierte Namen zu verwenden, wenn ein möglicher Konflikte besteht.

// 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);
}

Ausgabe

Int MyNamespace::myFunction

Vorlagenmehrdeutigkeit

Visual Studio 2012 erzwingt die C++98/03/11-Standardregeln für die Mehrdeutigkeit mit der Schlüsselwort (keyword) "Vorlage". Im folgenden Beispiel akzeptiert Visual Studio 2010 sowohl die Nichtkonformingzeilen als auch die übereinstimmenden Zeilen. Visual Studio 2012 akzeptiert nur die konformen Linien.

#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;
}

Eine Übereinstimmung mit den Mehrdeutigkeitsregeln ist erforderlich, da C++ standardmäßig annimmt, dass AY::Rebind keine Vorlage ist, und der Compiler deshalb folgenden "<"-Code als "less-than" interpretiert. Er muss wissen, dass Rebind eine Vorlage darstellt, sodass er "<" ordnungsgemäß als spitze Klammer analysieren kann.

Siehe auch

Namensauflösung