Концепции C ++: проверка на создание шаблона - PullRequest
0 голосов
/ 14 января 2019

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

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

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

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

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

Ответы [ 3 ]

0 голосов
/ 14 января 2019

Используя дедукцию аргументов шаблона класса 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>;

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


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

0 голосов
/ 15 января 2019

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

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>;
0 голосов
/ 14 января 2019

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

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;

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

...