【问题标题】:Initializer list of static field in template class fails with clang模板类中静态字段的初始化程序列表因 clang 而失败
【发布时间】:2012-12-28 09:53:00
【问题描述】:

以下代码片段在 g++ 和 clang++ 下运行良好:

// bsp1.cc
class A {
public:
  A(int, char const *);

  int value;
  const char * name;
};

class B {
public:
  static const A many_as[];
};

A const B::many_as[] 
{ { 0, "zero" }, 
    { 1, "one" }, 
    { 2, "two" }, 
    { 3, "three" }, 
    { 77, 0 } };

当我将 B 类更改为模板时:

// bsp2.cc
class A {
public:
  A(int, char const *);

  int value;
  const char * name;
};

template<typename T>
class B {
public:
  static const A many_as[];
};

template<>
A const B< int >::many_as[] 
{ { 0, "zero" }, 
  { 1, "one" }, 
  { 2, "two" }, 
  { 3, "three" }, 
  { 77, 0 } };

clang++ 失败:

tmp/bsp2.cc:19:1: error: expected ';' after top level declarator
{ { 0, "zero" }, 
^
1 error generated.

g++ 对此仍然很满意。

版本信息: g++ (Debian 4.7.2-4) 4.7.2, clang 3.3 版(主干 171722)

当我将= 添加为时

A const B< int >::many_as[] =

clang++ 也很开心。

我的问题:

  1. bsp2.cc 有效吗? (换句话说:这是clang++的问题吗?)
  2. bsp2 有和没有= 之间在语义上有什么区别吗? (即我可以使用带有= 的版本作为“解决方法”吗?)
  3. (额外问题:)您能否指出 C++ 11 标准中描述这一点的段落?

【问题讨论】:

    标签: c++ templates static c++11 clang


    【解决方案1】:

    9.4.2p2 指定非模板静态数据成员的定义;暗示,它的语法与任何其他定义相同,因此 brace-or-equal 初始化器brace-init-list 绝对没问题。 14p1 和 14.5.1.3 涵盖了模板静态数据成员的显式特化的定义,并且再次暗示静态数据成员的任何有效定义对于模板静态数据成员显式特化的定义都是有效的.

    确实,14.7.3p13 明确演示了在模板静态数据成员显式特化中使用 braced-init-list 来区分默认初始化和定义:

    struct X {};
    template<typename> struct Q { static X i; };
    template<> X Q<int>::i{};
    

    由于 clang 无法从标准中的示例中接受此语法,因此很明显 bug 存在于 clang 中。

    在这种情况下,您的解决方法绝对有效。插入= 的语义含义 (8.5p14) 是 direct-initialization (8.5p16) 更改为 copy-initialization (8.5p15)。由于您的初始化程序是 braced-init-list (8.5p17),因此会执行 list-initialization (8.5.4),并从 direct-list-初始化copy-list-initialization (8.5.4p1),但是由于您的对象是一个数组,因此是一个聚合 (8.5.1p1),因此会执行聚合初始化,这对直接/复制初始化的区别。

    请注意,A 上存在构造函数会阻止它成为聚合,这意味着构造函数很可能在运行时被调用。如果您删除构造函数,那么A 的数组将是一个递归聚合,并且可以在编译时完全初始化(数据将直接放入您的目标文件中)。

    【讨论】:

    • 是的 - 用新版本检查过:干得好!
    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多