Почему компилятор не генерирует код для статической переменной-члена моего неустановленного класса шаблона?

Этот вопрос трудно сформулировать, в первую очередь из-за терминов «создание экземпляров класса» и «создание экземпляров шаблона». У меня есть шаблонный класс, полный статических функций и членов. Перед первым использованием каждой специализации этого шаблона необходимо выполнить некоторую инициализацию.

Мой первоначальный план состоял в том, чтобы просто дать классу шаблона статический член initializer, который будет инициализировать статические члены класса шаблона во время его создания при динамической инициализации.

Однако это не работает. Если я явно не вызову код в классе initializer, компилятор не будет генерировать для него код или хранилище.

Например:

template<typename Tag>
class WorkerPool
{
    struct WorkerInitializer
    {
        void foo() { }
        WorkerInitializer() { WorkerPool<Tag>::start(); }
    };
    friend struct WorkerInitializer;
    static WorkerInitializer _initializer;

    static void start() { std::cout << "Started" << std::endl; }

public:
    static void async() { std::cout << "Async" << std::endl; }
};

template<typename T> typename WorkerPool<T>::WorkerInitializer 
WorkerPool<T>::_initializer;


struct GenericWorker { };
int main()
{
    WorkerPool<GenericWorker>::async();
}

На выходе получается просто «Асинхронный».

Однако, если я изменю его так, что вызов WorkerPool<T>::async() вызовет _initializer.foo(), то инициализатор будет скомпилирован и правильно сконструирован, как я и ожидал.

Почему компилятор отказывается генерировать код для моего статического члена?

Я тестировал Visual Studio 2010/2012, gcc и clang, и все они дали одинаковый результат; мой статический член не построен. Это заставляет меня думать, что стандарт требует такого поведения, но мне трудно понять, почему это может быть.


person Collin Dauphinee    schedule 08.03.2013    source источник