Самый простой способ - просто использовать его.Шаблоны C ++ полностью утка и не очень проверены, пока вы не передадите фактический тип.
Вы можете использовать методы, основанные на SFINAE, для тестирования подобных вещей ...
namespace details {
template<template<class...>class Z, class, class...>
struct can_apply:std::false_type{};
template<class...>struct voider {using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
этопомощник SFINAE, который определяет, можете ли вы применить шаблон к пачке типов.
template<class X, class Y=X>
using raw_less_r = decltype( std::declval<X>()<std::declval<Y>() );
template<class X, class Y=X>
using can_raw_less = can_apply<raw_less_r, X, Y>;
и теперь can_raw_less<int>
является производным от true_type
, если int < int
допустим, и false_type
в противном случае.
Затем мы уходим и:
template <typename Type, class=void>
class MyClass;
template <typename Type>
class MyClass<Type, std::enable_if_t<can_raw_less<Type>>>
{/*...*/}
используем SFINAE и enable_if_t
, чтобы создать специализацию, которая существует тогда и только тогда, когда Type<Type
действителен.
Примечаниечто лучший шаблон, вероятно, выглядит так:
template<class F, class...Args>
using invoke_result = decltype( std::declval<F>()( std::declval<Args>()... ) );
template<class F, class...Args>
using can_invoke = can_apply< invoke_result, F, Args... >;
template<class Type, class Cmp=std::less<Type>>
class MyClass {
static_assert( can_invoke< Cmp, Type const&, Type const& >{}, "You must be able to compare Type to itself" );
// use Cmp{}(Type, Type) to compare
};
, что и делают контейнеры std, с добавлением static_assert
для более чистых сообщений об ошибках.