Концепции C++: проверка на создание шаблона

Вопрос задан: 8 месяцев назад Последняя активность: 8 месяцев назад
up 1 down

Предполагая, что у меня есть шаблонный тип, например

template<typename A, typename B, typename C>
struct mytype { };

Как мне написать концепцию, которая проверяет, является ли тип экземпляром этого шаблона?

template<typename T>
concept MyType = requires(T x) { ??? }

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

3 ответа

up 3 down

Вы можете определить свою собственную метафункцию (type trait) для этой цели:

template <typename T>
struct is_mytype<T> : std::false_type { };

template <typename A, typename B, typename C>
struct is_mytype<mytype<A, B, C>> : std::true_type { };

template <typename T>
concept MyType = is_mytype<T>::value;

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

up 2 down accepted

Используя дедукцию аргументов шаблона класса C++ 17, вы сможете сделать что-то вроде этого:

template<typename A, typename B, typename C>
struct mytype { };

template<class T>
concept C1 = requires(T x) { 
    { mytype{x} } -> T;
};

mytype{x} использует вывод аргумента шаблона класса для вывода A, B а также C, так что это действительно, если вы можете построить mytype<A, B, C> из T. В частности, это действительно, если mytype копируемо, так как вы неявно объявили руководство по вычету копий похожий на:

template <typename A, typename B, typename C>
mytype(mytype<A, B, C>) -> mytype<A, B, C>;

Проверяя что T также построен mytype создание экземпляров во избежание сопоставления с другими руководствами по выводам, например, это будет соответствовать любому типу без -> T:

template <class A, class B, class C>
struct mytype {
    mytype(A);
};

template <class A>
mytype(A) -> mytype<A, A, A>;

Предложенное решение не работает для классов, не допускающих копирования, даже при том, что должно быть возможно заставить его работать для классов только для перемещения.


Протестировано с:

up 1 down

Вы можете написать обобщенную характеристику для проверки специализаций:

template <typename T, template <typename...> class Z>
struct is_specialization_of : std::false_type {};

template <typename... Args, template <typename...> class Z>
struct is_specialization_of<Z<Args...>, Z> : std::true_type {};

template <typename T, template <typename...> class Z>
inline constexpr bool is_specialization_of_v = is_specialization_of<T,Z>::value;

Что вы можете сделать в обобщенной концепции:

template<typename T, template <typename...> class Z>
concept Specializes = is_specialization_of_v<T, Z>;

template<typename T>
concept MyType = Specializes<T, mytype>;

или просто специализированный:

template<typename T>
concept MyType = is_specialization_of_v<T, mytype>;