Resolución de nombres para los tipos dependientes

Utilice typename para los nombres completos en definiciones de plantilla, para indicar al compilador que el nombre completo dado identifica un tipo. Para obtener más información, vea 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.

La búsqueda de nombres para nombres dependientes examina los nombres tanto del contexto de la definición de la plantilla (en el siguiente ejemplo, este contexto buscaría myFunction(char)) como del contexto de la creación de una instancia de la plantilla. En el siguiente ejemplo, la plantilla se instancia en main; por lo tanto, MyNamespace::myFunction es visible desde el punto de creación de instancias y se elige como la mejor coincidencia. Si MyNamespace::myFunction cambiase de nombre, se llamaría a myFunction(char) en su lugar.

Todos los nombres se resuelven como si fueran nombres dependientes. Sin embargo, recomendamos utilizar nombres completos si hay alguna posibilidad de conflicto.

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

Salida

Int MyNamespace::myFunction

Desambiguación de plantilla

Visual Studio 2012 aplica las reglas estándar de C++98/03/11 para la eliminación de ambigüedades con la palabra clave "plantilla". En el ejemplo siguiente, Visual Studio 2010 aceptaría las líneas no conformes y las líneas conformes. Visual Studio 2012 acepta solo las líneas conformes.

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

Se requiere la conformidad con las reglas de desambiguación, porque, de forma predeterminada, C++ supone que AY::Rebind no es una plantilla, por lo que el compilador interpreta el siguiente “<” como "menos que". Debe saber que Rebind es una plantilla para que pueda analizar correctamente “<” como un corchete angular.

Consulte también

Resolución de nombres