Вы можете проверить, существует ли структура или нет, если вы считаете, что предварительное объявление не существует.
В этом примере предполагается, что либо TestData
всегда определено, либо никогда не определено:
#include <type_traits>
// Comment this line to trigger the static assert
struct TestData {};
template<typename, typename = void>
struct MaybeData {};
template<typename T>
struct MaybeData<T, std::void_t<decltype(sizeof(T))>> {
T data;
};
struct TestContainer : MaybeData<struct TestData> {};
Мы можем протестировать наше решение следующим образом:
template<typename, typename = void>
constexpr auto has_data = false;
template<typename T>
constexpr auto has_data<T, std::void_t<decltype(T::data)>> = true;
static_assert(has_data<TestContainer>);
Механизм, стоящий за этим, заключается в том, что вместо отправки самой структуры (TestData
) в качестве типа, мы используем struct TestData
в качестве аргумента, который ссылается на тип, если он существует, но в дальнейшем объявляем его, если нет.
Затем мы используем sfinae, чтобы проверить, является ли sizeof(T)
допустимым выражением. Если TestData
является неполным типом, выражение недопустимо.
Однако, если полнота типа изменяется между экземплярами шаблона, программа плохо сформирована.
Живой пример