问题 我们可以将匿名结构作为模板参数吗?


标题是不言自明的,但这是一个简化的例子:

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

}

当我尝试使用匿名结构作为模板参数时,编译器会抱怨。在没有单独的命名结构定义的情况下,实现这样的事情的最佳方法是什么?


11144
2018-01-01 03:28


起源



答案:


你不被允许 确定 一个未命名的类型作为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
}

7
2018-01-01 03:36



在C ++ 0x中,可以推导出未命名类型的对象作为模板参数,但我不认为可以在模板参数列表中显式指定未命名的类型。 - James McNellis
Prasoon,请问我参考标准的正确部分吗?我的测试用例有一个未命名的结构(传递给typedef,但我们都知道typedef名称不是结构名称)编译得很好。 - Ben Voigt
@Ben: 14.3.1/2 - Prasoon Saurav
@Prasoon:谢谢。看起来在C ++ 0x中肯定会删除该限制。仍然无法在模板参数列表中定义类型,这是代码实际提出的问题(与标题相对)。 - Ben Voigt
感谢澄清参数与参数 - 我想我总是只是交替使用这些术语,但是,我的意思是参数。我尝试使用本地定义的命名结构作为模板 论据 但结果是一样的。 (我正在使用GCC 4.5的C ++ 0x支持。) - nonoitall


答案:


你不被允许 确定 一个未命名的类型作为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
}

7
2018-01-01 03:36



在C ++ 0x中,可以推导出未命名类型的对象作为模板参数,但我不认为可以在模板参数列表中显式指定未命名的类型。 - James McNellis
Prasoon,请问我参考标准的正确部分吗?我的测试用例有一个未命名的结构(传递给typedef,但我们都知道typedef名称不是结构名称)编译得很好。 - Ben Voigt
@Ben: 14.3.1/2 - Prasoon Saurav
@Prasoon:谢谢。看起来在C ++ 0x中肯定会删除该限制。仍然无法在模板参数列表中定义类型,这是代码实际提出的问题(与标题相对)。 - Ben Voigt
感谢澄清参数与参数 - 我想我总是只是交替使用这些术语,但是,我的意思是参数。我尝试使用本地定义的命名结构作为模板 论据 但结果是一样的。 (我正在使用GCC 4.5的C ++ 0x支持。) - nonoitall


你的问题不是结构是未命名的,而是结构是在本地声明的。在C ++ 03中不允许使用本地类型作为模板参数。它将在C ++ 0x中,因此您可以尝试升级编译器。

编辑:实际上,你的问题是,根据C ++标准,在模板参数列表中放置类定义(有或没有名称)不合法。

litb指出虽然它适合C ++ 0x语法,但是禁止在此定义类型 [dcl.type]

类型-peci-seq不应该定义类或枚举,除非它出现在别名声明(7.1.3)的type-id中,而不是模板声明的声明。

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

4
2018-01-01 03:35



实际上我正在使用GCC 4.5的C ++ 0x功能。这个功能还没有在那里实现吗? - nonoitall
@nonoitall:The C ++ 0x标签wiki 链接到许多编译器中有关C ++ 0x支持状态的大量信息。它说它应该在gcc 4.5中添加。该 官方gcc发布说明 说“在C ++ 0x模式下,本地和匿名类现在被允许作为模板参数”。你正在编译 -std=gnu++0x 选项,对吗? - Ben Voigt
我的错。显然这是GCC 4.5的MinGW端口遗留下来的东西。尝试在Linux机器上编译它,它将在使用本地定义的结构时进行编译(尽管使用匿名结构作为参数仍然不会飞)。 /我去安装Cygwin。 - nonoitall
“......它不应出现在type-id中。”只是想说“使用foo = foo;”是禁止的。它讨论了这样的别名声明。当决议 open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1044 应用,然后可以删除该文本。 - Johannes Schaub - litb
@Johannes:谢谢!还有“嘿蝙蝠信号有效!”您对在模板参数列表中实际定义类型的评估是什么? - Ben Voigt