переменная шаблона thread_local структуры внутри анонимного пространства имен не может связать? - PullRequest
1 голос
/ 11 апреля 2019

В следующем примере программы используется переменная локального шаблона потока и создается ее экземпляр с использованием типа в анонимном пространстве имен. Это приводит к ошибке компоновщика в gcc. В clang он на самом деле компилируется, но не работает правильно.

#include <stdio.h>

template<typename T>
struct container {
    container()  { printf("construct: %p\n", this); }
    ~container() { printf("destruct: %p\n", this);  }
};

template<typename T>
thread_local container<T> storage;

namespace {
    struct bar {};
}

int main() {
    auto& ref1 = storage<bar>;
    auto& ref2 = storage<bar>;
}

На gcc это завершается с ошибкой ссылки:

a.cpp:6:2: warning: ‘container<T>::~container() noexcept [with T = {anonymous}::bar]’ used but never defined
  ~container() { printf("destruct: %p\n", this);  }
  ^
/tmp/ccgh0P15.o: In function `__tls_init':
a.cpp:(.text+0xa9): undefined reference to `container<(anonymous namespace)::bar>::~container()'

С помощью clang программа компилируется, но выдает очень тревожный вывод:

construct: 0x7fb8d1c003d0
construct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0

Есть ли некоторые неровности вокруг thread_local / шаблонных переменных, с которыми я здесь сталкиваюсь? Мне неясно, почему это когда-либо приведет к ошибке ссылки (ошибка ссылки исчезнет, ​​если я удалю thread_local). В случае clang, как двойное уничтожение объекта со статической продолжительностью хранения может быть чем угодно, только не ошибкой компилятора? В clang проблема исчезает, если я удаляю анонимное пространство имен ИЛИ спецификацию thread_local ИЛИ, удаляя одну из ссылок в main ().

Может кто-нибудь пролить свет на это, мне в основном просто любопытно, если я что-то неправильно понимаю. Спасибо!

EDIT:

clang++ -v

Apple LLVM version 10.0.0 (clang-1000.11.45.5)

g++ -v

gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
...