Является ли специализация неявно созданной, если она уже была неявно создана?
Вопрос в названии достаточно понятен. Чтобы быть более конкретным, рассмотрим следующий пример:
#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://stackru.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 ответ
Является ли специализация неявно созданной, если она уже была неявно создана?
Нет. Согласно [temp.point]/8:
Специализация для шаблона класса имеет не более одной точки создания экземпляра в единице перевода.
x<char>
нужно создавать только один раз, а не тогда, когда он назван в первом статическом утверждении, только перед ch
, Но [temp.point]/8 также говорит
Специализация для шаблона функции, шаблона функции-члена или функции-члена или статического члена данных шаблона класса может иметь несколько точек создания экземпляров в единице перевода и в дополнение к описанным выше точкам создания экземпляров для любого такого специализация, которая имеет точку создания экземпляра внутри единицы перевода, конец единицы перевода также считается точкой создания экземпляра. [...] Если две разные точки инстанцирования придают специализации шаблона разные значения в соответствии с правилом единого определения, программа некорректна, диагностика не требуется.
А также is_complete_helper::test
это шаблон функции-члена, объявление которого создается перед статическим утверждением. Таким образом, он также должен иметь экземпляр в конце TU. Где это, скорее всего, даст другой результат. Так что эта черта зависит от плохо сформированной конструкции NDR.