g ++可变参数模板问题

时间:2018-05-14 21:11:18

标签: c++ g++ variadic-templates

所以我把这个程序给了g ++和clang(在Linux,x86_64上):

#include <iostream>

using namespace std;

template<char... Cs>
struct A {
  static const string s;
  static A a;
  ~A() {
    cout << "s = " << s << "\n";
  }
};

template<char... Cs>
const string A<Cs...>::s = {{Cs...}};

template<char... Cs>
A<Cs...> A<Cs...>::a;

int main(void)
{
  (void)A<'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'>::a;

  return 0;
}

Clang输出{{​​1}}(如预期的那样)。

g ++(版本5到8)输出s = aaaaaaaaaaaaaaaa(非常意外)。

如果您不使用可变参数模板,则不会发生这种情况(如果您删除所有&lt;&gt;代码并内联字符列表以初始化s = s = aaaaaaaa

如果用字符数组替换A::s(并改为使用std::string),也不会发生这种情况。

这段代码不是故意的,还是编译器错误?

1 个答案:

答案 0 :(得分:8)

您的代码不正确。标准的重要部分是6.6.3 / 1 [basic.start.dynamic] 在N4659:

  

如果变量是a,则静态存储持续时间的非局部变量的动态初始化是无序的   隐式或显式实例化的专业化[...]

因为初始化没有排序,所以不能依赖于破坏的顺序。无论施工顺序如何,任何订单都是合法的。见6.6.4 / 3 [basic.start.term]

因此,在崩溃s之前,允许gcc销毁a, 这是发生了什么,并导致奇怪的输出。 Live