g ++可变参数模板问题 [英] g++ variadic template issue
问题描述
因此,我将此程序提供给了g ++和clang(在Linux和x86_64上均如此):
So I gave this program to g++ and clang (both on 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输出s = aaaaaaaaaaaaaaaa
(按预期).
Clang outputs s = aaaaaaaaaaaaaaaa
(as expected).
g ++(版本5到8)输出s = s = aaaaaaaa
(非常意外).
g++ (versions 5 until 8) outputs s = s = aaaaaaaa
(pretty unexpected).
如果不使用可变参数模板,则不会发生这种情况(如果删除所有<>代码并内联字符列表以初始化A::s
.
This doesn't happen if you don't use the variadic template (if you remove all the <> code and inline the character list to initialize A::s
.
如果将std::string
替换为字符数组(并改为使用A<Cs...>::s = {Cs...}
),也不会发生这种情况.
It also doesn't happen if you replace the std::string
by a character array (and use A<Cs...>::s = {Cs...}
instead).
这不是代码,还是编译器错误?
Is this code not meant to be, or is it a compiler bug?
推荐答案
您的代码不正确.该标准的重要部分是6.6.3/1 [basic.start.dynamic] 在N4659中:
Your code is incorrect. The important part of the standard is 6.6.3/1 [basic.start.dynamic] in N4659:
具有静态存储持续时间的非局部变量的动态初始化是无序的,如果该变量是 隐式或显式实例化的专业化[...]
Dynamic initialization of a non-local variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization [...]
因为初始化没有顺序,所以您不能依赖销毁顺序.任何命令都是合法的,无论构造顺序如何.参见6.6.4/3 [basic.start.term]
Because the initialization is not ordered, you cannot rely on the order of destruction. Any order is legal, regardless of order of construction. See 6.6.4/3 [basic.start.term]
gcc在销毁a
之前销毁s
,
这是发生的并导致奇怪的输出. 实时.
gcc is thus allowed to destroy s
before it destroys a
,
which is what happens and causes the weird output. Live.
这篇关于g ++可变参数模板问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!