Resolução de nome para tipos dependentes
Use typename
para nomes qualificados em definições de modelo para dizer ao compilador que o nome qualificado fornecido identifica um tipo. Para obter mais informações, consulte 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.
A pesquisa de nomes para nomes dependentes examina nomes do contexto da definição do modelo — no exemplo a seguir, esse contexto encontraria myFunction(char)
— e do contexto da instanciação do modelo. No exemplo a seguir, o modelo é instanciado na principal; portanto, o MyNamespace::myFunction
é visível do ponto de instanciação e é escolhido como a melhor correspondência. Se MyNamespace::myFunction
fosse renomeado, myFunction(char)
seria chamado.
Todos os nomes são resolvidos como se fossem nomes dependentes. Entretanto, recomendamos que você use nomes totalmente qualificados se houver qualquer conflito possível.
// 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);
}
Saída
Int MyNamespace::myFunction
Desambiguação de modelo
O Visual Studio 2012 impõem as regras do padrão C++98/03/11 para a desambiguação com a palavra-chave “template”. No exemplo a seguir, o Visual Studio 2010 aceitaria as linhas fora de conformidade e as linhas em conformidade. O Visual Studio 2012 aceita apenas as linhas em conformidade.
#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;
}
A conformidade com as regras de desambiguação é necessária porque, por padrão, o C++ presume que AY::Rebind
não seja um modelo e, assim, o compilador interpreta o seguinte “<
” como menor que. Ele precisa saber que Rebind
é um modelo para poder analisar corretamente “<
” como um colchete angular.
Confira também
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de