Можем ли мы иметь анонимную структуру в качестве аргумента шаблона?

Название довольно понятно, но здесь упрощенный пример:

#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