Разрешение имен зависимых типов
Используйте 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)
и контекст создания экземпляра шаблона. В следующем примере шаблон создается в основном; таким образом, 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 применяет стандартные правила C++98/03/11 для диамбигуации с ключевое слово шаблона. В следующем примере Visual Studio 2010 принимает как несоответствующие строки, так и соответствующие строки. Visual Studio 2012 принимает только соответствующие строки.
#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
" как угловую скобку, он должен знать, что <
— это шаблон.
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по