Рассмотрим этот код,
template<class T>
struct Sample
{
typename T::X *x; //declare pointer to T 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
дают достаточно ясно компилятору, что все, что следует за ним, это тип, не.
Итак, мой вопрос: зачем компиляторам по-прежнему нужно ключевое слово typename
, даже в недвусмысленных ситуациях, например, когда мы используем typedef
и new
?
EDIT (после прочтения этого ответа от Johannes Schaub):
//typedef NOT followed by a type!
int typedef A;
Этот синтаксис просит меня немного изменить свой вопрос, так что точка, которую я пытаюсь сделать, может быть замечена другими.
Рассмотрим это,
T::X typedef *x;
Итак, из контекста все еще достаточно ясно для компилятора, что T:: X является типом, независимо от того, появляется он перед typedef
или после typedef
. Если С++ не позволяет нам писать typedef 5 five
или typedef T::value t_value
(где T:: значение является значением), наличие 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. Пожалуйста, взгляните на него перед ответом.: -)