Edit:
В вашем коде нет подводных камней, извините за это. Но этот ответ позволяет вам писать код, похожий на C++20
concept
:
template <class T>
auto& operator << (std::ostream &out, const printable_t<T> &t)
{
t.print_to(out);
return out;
}
На самом деле я написал библиотеку C++17
concept_check на основе detector
и может использоваться таким образом.
Для получения дополнительной информации о поддержке concept
в C++20
, взгляните на эти 2: Ограничения и понятия (начиная с c ++ 20) и Ограничения и понятия (TS)
Оригинальный ответ:
std :: эксперимент :: is_detector может сделать магию для вас. Хотя его нет в стандартной библиотеке, его нетрудно реализовать, и эта ссылка дает предлагаемую реализацию.
Здесь я дам вам, как обнаружить эту функцию, вместе с моей реализацией is_detected_v
.
#include <type_traits>
#include <utility>
#include <ostream>
// For support for C++17 is not complete in many compiler, I also define void_t
template <class...> using void_t = void;
namespace impl {
template <class Default, class AlwaysVoid, template <class...> class Op, class ...Args>
struct detector: private std::false_type
{
using std::false_type::value;
using type = Default;
};
template <class Default, template <class...> class Op, class ...Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>: private std::true_type
{
using std::true_type::value;
using type = Op<Args...>;
};
} // namespace impl
struct nonsuch {};
#define CONCEPT_T constexpr const static inline bool
template <template<class...> class Op, class ...Args>
CONCEPT_T is_detected_v = impl::detector<nonsuch, void, Op, Args...>::value;
// Detect whether print_to exists.
template <class T>
using print_to_ret_t = decltype( std::declval<T>().print_to( std::declval<std::ostream&>() ) );
template <class T>
CONCEPT_T has_func_print_to_v = is_detected_v<print_to_ret_t, T>;
template <class T, std::enable_if_t< has_func_print_to_v<T> >>
using printable_t = T;
#undef CONCEPT_T
Вы можете попытаться добавить поддержку C++14
к этому коду. Это не будет слишком сложно. CONCEPT_T
необходимо изменить на constexpr const static bool
, чтобы настроить на C++14
.