2015-06-16 3 views
6

С практической точки зрения, я понимаю, что оба typedef и test несколько «лишние» и должны быть удалены, если мы хотим, чтобы следующий код для компиляции:Почему шаблоны typedef незаконны?

template< typename type_t > 
typedef struct tagTest 
{ 
    int a; 
} test; 

Однако, я думал, что множество Объявление typedef было подмножеством набора объявлений. У них только что был этот специфический decl-specifier. Это была моя рационализация для

typedef struct tagTest 
{ 
    int a; 
} test; 

представляя идентификатора testи объявить структуру tagTest. Если эта интерпретация верна, то следующий абзац из стандарта должен позволять templatetypedef (хотя и не со значением, задаваемым ключевым словом using).

декларация в матричной декларации, - (1.1) объявить или определить функцию, класс, или переменную, или - (1.2) определить функцию-член, класс член , член перечисления, или статический член данных шаблона класса или класса вложен в шаблоне класса или - (1.3) определить шаблон члена шаблона класса или класса, или - (1.4) быть объявлением псевдонима.

Я не вижу ошибки в своих рассуждениях, но заключение является незаконным.

Каковы соответствующие части стандарта, которые разрешают вышеупомянутую головоломку?


UPDATE Часть вышеприведенных рассуждений использует тот факт, что typedefstruct объявляющий структуру. Спецификатор typedef, насколько я понимаю, подразумевает, что любые объявленные переменные действительно являются типами. То есть typedef обновляет test от простой переменной до типа, эквивалентного объявленному tagTest. Вот почему следующий код компилируется (хотя и с предупреждением).

typedef struct tagTest 
{ 
    int a; 
}; 
tagTest t; 

Один из ответов заботится о избыточном test.Но, можно использовать ЬурейеЕ без описателя because «Init-описатель-лист не является обязательным при объявлении имени класса/структуры/объединения или именованный перечисление»

+0

Er ... Ни один из этих случаев не закрывает его. Тот факт, что в декларации содержится что-то, объявляющее класс, не означает, что само объявление объявляет класс. Декларация просто определяет тип. – hvd

+0

@hvd В C, typedef, содержащий помеченную структуру, объявляет эту структуру, а также определяет имя, которое его псевдонизирует. Вы говорите, что C++ отличается в этом отношении? – davmac

+0

@ davmac Нет, мы согласны с окончательным результатом такой декларации. Я говорю, что часть, которая заставляет объявлять структуру, - это не сама декларация, а только подкомпонент этого объявления. И это относится как к C, так и к C++. – hvd

ответ

3

Template typedefs не разрешался предварительно C++, 11 и с 11 template aliases C++, были введены для решения эти проблемы. ЧФР. C++ template typedefs и wikipedia.

Так, как вы отметили, стандарт не позволяет typedef быть там, код неверен

псевдоним декларации:

using identifier attribute-specifier-seqopt= type-id ; 

typedef декларации не объявления псевдонима.

Кроме того, вы не можете иметь описатель, если вы объявить шаблон класса, это явно запрещено стандартным

[Темп]/р3

В матричной декларации , явная специализация или явное создание экземпляра init-declarator-list в объявлении должно содержать не более одного декларатора. Когда такое объявление используется для объявления шаблона класса, не разрешен декларатор.

, так что даже не следующий будет компилировать

template< typename type_t > 
struct tagTest 
{ 
    int a; 
} test; 

Edit:

Нигде не указано, что

typedef struct S { }; 

должна быть ошибка, таким образом, как GCC и clang принять его с предупреждением. Я предполагаю, что Clang рассчитывает на [TEMP]/3 выдавать ошибку в случае ЬурейеЕ, использовавшийся с шаблоном, а GCC отвергает этот код сразу

template<typename T> 
typedef struct S { }; 

ЧФР. clang bug 22249

+0

Удаление токена 'test', но сохранение спецификатора' typedef' должно быть законным, поскольку деклараторы являются необязательными. – Hector

+0

@Hector отредактировал вопрос, чтобы добавить подробную информацию для этого случая –

+0

+1 Эта ссылка о clang nice. Но в отношении вашего вступительного абзаца я не утверждаю, что 'template typedef struct S {};' должен работать так же, как и ключевое слово 'use'. Я утверждаю, что стандарт позволяет ему быть законным с тем же значением, что и 'template struct S {};'. – Hector

1

Независимо от того, что typedef определяет, что является typedef декларация , который не указан в этих случаях:

  • [член] функция
  • [член] класс
  • переменная
  • член перечисления
  • статический член данных шаблона класса/класса вложен в шаблоне класса
  • шаблон
  • члена шаблона класса или класса
  • псевдоним декларации

И просто быть ясно typedef декларации не объявления псевдонима. Алиас декларация, как указано в грамматике в § 7 стандарта являются:

псевдоним декларации:

using identifier attribute-specifier-seqopt= type-id ;

Не говоря уже о том, что если бы это было возможно, то объявление шаблона using будет не таким «крутым», как сегодня, и there would be little to no sense to have both.

+0

Я думаю, что точка OPs заключается в том, что текст не указывает _not_, что декларация должна быть объявлена ​​как «[член] класса» (среди других типов), а скорее «объявляет или определяет» класс, который typedef со структурой субапредация, возможно, делает. – davmac

1

C не поддерживает шаблоны и синтаксис

typedef struct tagX { 
} X; 

в C++ является рудиментарным C, то для обеспечения постоянной поддержки для C заголовков и т.д., а не для использования в реальных C++.

на сообщении ++ синтаксис С для вышеперечисленного

struct X {}; 

(YMMV на распорном размещении)

Смежные вопросы