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

Я ожидаю, что следующее будет плохо сформировано NDR, но это не так 🙁

#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 разных значения в зависимости от точек реализации.

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

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

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

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

3

Решение

Я ожидаю, что следующее будет плохо сформировано NDR, но это не так 🙁

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

Тем не менее, соответствующее правило здесь [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) является допустимым выражением.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]