Ожидание разных типов в зависимости от точки создания

Я ожидаю, что следующий отчет о недоставке будет неправильно сформирован, но, похоже, нет :-(

#include <type_traits>

template <typename T, typename Enabler = void>
struct is_complete : std::false_type {};

template <typename T>
struct is_complete<T, std::void_t<decltype(sizeof(T) != 0)>> : std::true_type {};

class X;

static_assert(!is_complete<X>::type{}); // incomplete type

class X {};

static_assert(!is_complete<X>::type{}); // complete, but already instantiated

Демо

Примечание: предположение, что sizeof(T) != 0 допустимо для признаков полноты (поскольку никакие типы не могут иметь sizeof(T) == 0, использование другой константы заставит найти лучшее имя для признаков :-))

Это вариант кода из Создается ли неявно специализация, если она уже была неявно создана?, если программа была объявлена ​​неверно сформированной программой, Диагностика не требуется (NDR), поскольку метод is_complete_helper<X>::test<X> имеет 2 разных значения в зависимости от точек реализации.

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

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

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

Я не прав ? или, к сожалению, эта программа верна.


person Jarod42    schedule 10.09.2018    source источник
comment
Я считаю, что сочетание этого и этого это отвечает на ваш вопрос   -  person Shafik Yaghmour    schedule 10.09.2018


Ответы (1)


Я ожидаю, что следующий отчет о недоставке будет неправильно сформирован, но, похоже, нет :-(

Вы не можете использовать тот факт, что программа компилируется (и запускается) как доказательство того, что она не является неправильно сформированной, отчет о недоставке. Точно так же, как вы не можете использовать кажущиеся допустимыми выходные данные программы, чтобы продемонстрировать, что она не демонстрирует неопределенного поведения.

При этом соответствующее правило здесь: [temp.point] / 8 < / а>:

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

У нас есть только одна точка создания экземпляра is_complete<X>: она находится прямо перед первым static_assert. Итак, это "нормально" - это, возможно, сбивает с толку и плохо, но это хорошо сформировано.

Но, однако, если мы разделим это:

// a.cpp
struct X;
static_assert(!is_complete<X>::value);

// b.cpp
struct X { };
static_assert(is_complete<X>::value);

Теперь это плохо сформировано, диагностику не требуется.


Обратите внимание, вам не нужен sizeof(T) != 0. Просто sizeof(T) в порядке. Вы не можете взять sizeof неполного типа, поэтому вам просто нужно проверить, что sizeof(T) является допустимым выражением.

person Barry    schedule 10.09.2018
comment
Верно. Я на мгновение растерялся :) - person Rakete1111; 10.09.2018
comment
Мой кажется, что нет в основном из-за обсуждения связанного вопроса, и действительно, компилятор не может использоваться для подтверждения NDR ;-). Печально, что код правильный :-(, особенно когда небольшая невинная вариация делает его плохо сформированным (например, явно используется статический член данных value вместо наследования bool_constant). - person Jarod42; 11.09.2018