вопрос о вариативном шаблоне g ++ - PullRequest
0 голосов
/ 15 мая 2018

Итак, я передал эту программу 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 выводит s = aaaaaaaaaaaaaaaa (как и ожидалось).

g ++ (версии 5 до 8) выводит s = s = aaaaaaaa (довольно неожиданно).

Этого не произойдет, если вы не используете шаблон переменной (если вы удалите весь код <> и встроите список символов для инициализации A::s.

Этого также не произойдет, если вы замените std::string на массив символов (и вместо этого будете использовать A<Cs...>::s = {Cs...}).

Этот код не предназначен или это ошибка компилятора?

1 Ответ

0 голосов
/ 15 мая 2018

Ваш код неверен. Важной частью стандарта является 6.6.3 / 1 [basic.start.dynamic] в N4659:

Динамическая инициализация нелокальной переменной со статической продолжительностью хранения неупорядочена, если переменная неявно или явно конкретизированная специализация [...]

Поскольку инициализация не упорядочена, вы не можете полагаться на порядок уничтожения. Любой заказ легален, независимо от порядка строительства. См. 6.6.4 / 3 [basic.start.term]

Таким образом,

gcc разрешено уничтожать s до того, как оно уничтожит a, что и происходит, и вызывает странный вывод. 1012 * Живая *.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...