Создает ли одно правило определения одну статическую функциональную переменную?

В качестве примера рассмотрим этот заголовок:

#include <iostream>

template<bool = true>
struct A {
    A() {
        static int x;
        std::cout << &x << "\n";
    }
};

static A<> a;

Что делать, если у меня было два разных файла на С++, включая этот файл, - он будет печатать один и тот же адрес дважды, гарантированно? Что еще более важно, если x был объектом другого типа с нетривиальным конструктором, гарантировалось ли его выполнение только один раз?

Ответ 1

В стандарте [С++ 11 14.8/2] говорится:

Каждая специализированная функция шаблона, созданная из шаблона, имеет свою собственную копию любой статической переменной.

Я предполагаю (и искренне надеюсь), что функции-члены класса шаблона обрабатываются одинаково, хотя я не могу найти конкретный язык, который так говорит.

В любом случае, помимо обычных рисков, связанных с инициализацией статических переменных в многопоточном контексте, я уверен, что это будет нормально. A<true>::A() (а внутренний "static int A<true>::A::x" ) будет помечен как слабые символы, и одна версия будет выбрана во время соединения, как и любой другой шаблон. (Очевидно, что экземпляр A<false> был бы отличным от A<true>.)

Изменить комментарий:

О беспокойстве о разных единицах перевода, похоже, говорится в разделе [3.2/5], определяющем ODR:

Если D является шаблоном и определяется более чем в одной единицы перевода, тогда... [при условии, что определения идентичны]... программа должна вести себя так, как если бы было одно определение D.

Фактические требования - это немного больше языка-юриста (зависимые имена в момент создания экземпляра должны быть одинаковыми и т.д. и т.д.), но я думаю, что это бит, который ставит вас в ясный: -)