Является ли специализация неявно созданной, если она уже была неявно создана? - PullRequest
0 голосов
/ 06 сентября 2018

Вопрос в названии достаточно понятен.Чтобы быть более конкретным, рассмотрим следующий пример:

#include <type_traits>

template <typename T>
struct is_complete_helper {
    template <typename U>
    static auto test(U*)  -> std::integral_constant<bool, sizeof(U) == sizeof(U)>;
    static auto test(...) -> std::false_type;
    using type = decltype(test((T*)0));
};

template <typename T>
struct is_complete : is_complete_helper<T>::type {};

// The above is an implementation of is_complete from https://stackoverflow.com/a/21121104/5376789

template<class T> class X;

static_assert(!is_complete<X<char>>::type{}); 
// X<char> should be implicitly instantiated here, an incomplete type

template<class T> class X {};

static_assert(!is_complete<X<char>>::type{}); // #1

X<char> ch; // #2

Этот код компилируется с GCC и Clang .

Согласно [temp.inst] /1 :

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

X<char> неявно создается из-за static_assert(!is_complete<X<char>>::type{}), который генерирует неполный тип.

Затем, после определения X, #1 предполагает, что X<char> не создается снова (все еще не завершено), в то время как #2 предполагает, что X<char> действительно создается снова (становится полным типом).

Является ли специализация неявно созданной, если она уже была неявно создана?Почему разница между #1 и #2?

Интерпретация стандарта приветствуется.

1 Ответ

0 голосов
/ 06 сентября 2018

Является ли специализация неявно созданной, если она уже неявно создана?

Нет. Согласно [temp.point] / 8 :

Специализация для шаблона класса имеет не более одной точки реализации в единице перевода.

x<char> нужно создавать только один раз, и это не так, когда он назван в первом статическом утверждении, только до ch. Но [temp.point] / 8 также говорит

Специализация для шаблона функции, шаблон функции-члена, или функция-член или статический член данных шаблона класса может иметь несколько точек реализации в пределах единицы перевода, и в дополнение к пунктам создания экземпляров, описанным выше, для любого такая специализация, которая имеет точку конкретизации в рамках блок перевода, конец блока перевода также считается точка инстанцирования. [...] Если две разные точки инстанцирования придают специализации шаблона разные значения в соответствии с правилом единого определения, программа некорректна, диагностика не требуется.

И is_complete_helper::test - это шаблон функции-члена, объявление которого создается перед статическим утверждением. Таким образом, он также должен иметь экземпляр в конце TU. Где это, скорее всего, даст другой результат. Так что эта черта зависит от плохо сформированной конструкции NDR.

...