Можем ли мы иметь анонимную структуру в качестве аргумента шаблона? - PullRequest
11 голосов
/ 01 января 2011

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

#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;

}

Компилятор жалуется, когда я пытаюсь использовать анонимную структуру в качестве аргумента шаблона.Каков наилучший способ добиться чего-то подобного без необходимости иметь отдельное именованное определение структуры?

Ответы [ 2 ]

7 голосов
/ 01 января 2011

Вам не разрешено определять безымянный тип в качестве аргумента шаблона в C ++ 03 или даже в C ++ 0x.

Лучшее, что вы можете сделать для создания именованной структуры, локальной для main (в C ++ 0x 1 )

1: Вы не можете использовать локальный тип в качестве аргумента шаблона в C ++ 03, однако C ++ 0x допускает это.

Также ознакомьтесь с отчетом о дефектах здесь . В предлагаемом решении упоминается

Следующие типы не должны использоваться в качестве аргумента шаблона для параметра типа шаблона:

  • тип, имя которого не имеет связи
  • безымянный класс или тип перечисления, который не имеет имени для целей связывания (7.1.3 [dcl.typedef])
  • cv-квалифицированная версия одного из типов в этом списке
  • тип, созданный применением операторов объявления к одному из типов в этом списке
  • тип функции, который использует один из типов в этом списке

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

Вы имели в виду аргумент шаблона? Параметр шаблона отличается от аргумента шаблона.

Например

template < typename T > // T is template parameter
class demo {};

int main()
{
   demo <int> x; // int is template argument
}
5 голосов
/ 01 января 2011

Ваша проблема не в том, что структура безымянна, а в том, что структура объявлена ​​локально. Использование локальных типов в качестве аргументов шаблона запрещено в C ++ 03. Хотя это будет в C ++ 0x, так что вы можете попробовать обновить ваш компилятор.

РЕДАКТИРОВАТЬ: На самом деле ваша проблема в том, что внутри списка аргументов шаблона не разрешено помещать определение класса, с именем или без, в соответствии со стандартом C ++.

litb указывает на то, что хотя он вписывается в грамматику C ++ 0x, определение типа здесь запрещено [dcl.type]:

Спецификатор типа-seq не должен определять класс или перечисление, если он не указан в идентификаторе типа объявления псевдонима (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
...