Рассмотрим этот код,
template<class T>
struct Sample
{
typename T::X *x; //declare pointer to T's X
};
В приведенном выше коде ключевое слово typename
требуется компилятору, чтобы он мог различать между вложенными типами и вложенными значениями в шаблонах. Это означает, что при отсутствии ключевого слова typename
компилятор интерпретирует это как умножение T :: X на x,
T::X *x; //multiply T::X with x
Таким образом, в таких ситуациях, когда может возникнуть неоднозначность, ключевое слово typename
становится необходимым , чтобы устранить неоднозначности. Но есть несколько ситуаций, когда сам контекст устраняет неясности. другая тема обсуждает контексты базового класса и функциональных параметров (хотя последний не устраняет неоднозначность). В этой теме я особенно хочу обсудить два других контекста, которые кажутся однозначными , но нам все еще необходимо написать typename
,
typedef typename T::X xtype;
pX = new typename T::X;
В этих двух ситуациях ключевые слова typedef
и new
достаточно ясно дают понять компилятору, что все, что следует, это type , not value,
Итак, мой вопрос: зачем компиляторам все еще нужно ключевое слово typename
, даже в однозначных ситуациях, например, когда мы используем typedef
и new
?
РЕДАКТИРОВАТЬ (после прочтения этого ответа от Йоханнес Шауб ):
//typedef NOT followed by a type!
int typedef A;
Этот синтаксис просит меня немного изменить мой вопрос, чтобы другие, кого я пытаюсь объяснить, могли понять точку.
Учтите это,
T::X typedef *x;
Поэтому из контекста все еще достаточно ясно, что T :: X является типом, независимо от того, появляется ли он до typedef
или после typedef
. Если только C ++ не позволяет нам писать typedef 5 five
или typedef T::value t_value
(где T :: value value ), наличие typedef
само по себе устраняет все неоднозначности и, таким образом, typename
кажется быть излишним требованием Стандарта (в таких ситуациях) . Тот же аргумент верен и для new
.
Кроме того, я написал шаблон класса, который использует эту структуру в качестве аргумента шаблона:
struct A
{
struct X { string name; };
static const int X = 100;
};
Я особенно хочу знать, является ли следующий код (из конструктора) правильным (переносимым) или нет,
//two interesting statements
pX = new typename T::X; //T::X means struct X
product = T::X * p; //but here, T::X means int X
Полный код здесь в ideone. Пожалуйста, посмотрите на это, прежде чем ответить. : -)