Можем ли мы иметь анонимную структуру в качестве аргумента шаблона?
Название довольно понятно, но здесь упрощенный пример:
#include <cstdio>
template <typename T>
struct MyTemplate {
T member;
void printMemberSize() {
printf("%i\n", sizeof(T));
}
};
int main() {
MyTemplate<struct { int a; int b; }> t; // <-- compiler doesn't like this
t.printMemberSize();
return 0;
}
Компилятор жалуется, когда я пытаюсь использовать анонимную структуру в качестве аргумента шаблона. Какой лучший способ добиться чего-то подобного без необходимости иметь отдельное определение с именем struct?
Ответы
Ответ 1
Вам не разрешено определять неназванный тип в качестве аргумента шаблона в С++ 03 или даже в С++ 0x.
Самое лучшее, что вы можете сделать, чтобы создать именованную структуру local для main (в С++ 0x 1)
1: вам не разрешено использовать локальный тип в качестве аргумента шаблона в С++ 03, однако С++ 0x разрешает его.
Также просмотрите отчет о дефектах здесь. В предлагаемом решении упоминается
Следующие типы не должны использоваться в качестве аргумента-шаблона для параметра типа шаблона:
- тип, имя которого не имеет связей
- неназванный класс или тип перечисления, который не имеет имени для целей привязки (7.1.3 [dcl.typedef])
- cv-квалифицированная версия одного из типов в этом списке
- тип, созданный приложением операторов declarator для одного из типов в этом списке
- тип функции, который использует один из типов в этом списке
Компилятор жалуется, когда я пытаюсь использовать анонимную структуру в качестве параметра шаблона.
Вы имели в виду аргумент шаблона? Параметр шаблона отличается от аргумента шаблона.
Например
template < typename T > // T is template parameter
class demo {};
int main()
{
demo <int> x; // int is template argument
}
Ответ 2
Ваша проблема заключается не в том, что структура неназванная, это то, что структура объявляется локально. Использование локальных типов в качестве аргументов шаблона в С++ 03 запрещено. Он будет в С++ 0x, поэтому вы можете попробовать обновить свой компилятор.
EDIT: На самом деле, ваша проблема заключается в том, что внутри списка аргументов шаблона нет законного места для определения класса с именем или без него в соответствии со стандартом С++.
litb указывает, что, хотя он вписывается в грамматику С++ 0x, определение типа здесь запрещено [dcl.type]
:
Спецификация типа-seq не определяет класс или перечисление, если оно не указано в идентификаторе типа объявления alias (7.1.3), которое не является объявлением объявления шаблона.
simple-template-id:
template-name < template-argument-list_opt >
template-argument-list:
template-argument ..._opt
template-argument-list , template-argument ..._opt
template-argument:
constant-expression
type-id
id-expression
type-id:
type-specifier-seq abstract-declarator_opt
type-specifier-seq:
type-specifier attribute-specifier-seq_opt
type-specifier type-specifier-seq
type-specifier:
trailing-type-specifier
class-specifier
enum-specifier
class-specifier:
class-head { member-specification_opt }
Некоторое время у меня возник вопрос о именах typedef, но litb очистил это. Они разрешены в качестве аргументов шаблона через:
trailing-type-specifier:
simple-type-specifier
elaborated-type-specifier
typename-specifier
cv-qualifier
simple-type-specifier:
:: opt nested-name-specifier_opt type-name
:: opt nested-name-specifier template simple-template-id
char
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
auto
decltype-specifier
type-name:
class-name
enum-name
typedef-name
simple-template-id