简体   繁体   中英

g++ variadic template issue

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 outputs s = aaaaaaaaaaaaaaaa (as expected).

g++ (versions 5 until 8) outputs s = s = aaaaaaaa (pretty unexpected).

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 .

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?

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 [...]

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 is thus allowed to destroy s before it destroys a , which is what happens and causes the weird output. Live .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM