Some c++ type tests which i found useful:
is_range
IsStreamInsertable
is_callable
is_searchable
is_vector
is_container
Checks if std::begin
or std::end
can be applied to T
.
struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
// Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
using std::begin;
using std::end;
not_this_one begin( ... );
not_this_one end( ... );
template <typename T>
struct is_range {
static const bool value =
!std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
!std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
};
#if defined(_MANAGED) // Managed types are never ranges
template <typename T>
struct is_range<T^> {
static const bool value = false;
};
#endif
template <typename T, typename = void>
struct StringMaker {
...
}
template<typename R>
struct StringMaker<R, typename std::enable_if<is_range<R>::value
&& !::Catch::Detail::IsStreamInsertable<R>::value
>::type> {
}
Checks if a operator<<
is available for T
.
template<typename T>
class IsStreamInsertable {
template<typename SS, typename TT>
static auto test(int)
-> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
template<typename, typename>
static auto test(...)->std::false_type;
public:
static const bool value = decltype(test<std::ostream, const T&>(0))::value;
};
Checks if T
can be called.
template<typename T>
struct is_callable_impl {
private:
typedef char(&yes)[1];
typedef char(&no)[2];
struct Fallback { void operator()(); };
struct Derived : T, Fallback { };
template<typename U, U> struct Check;
template<typename>
static yes test(...);
template<typename C>
static no test(Check<void (Fallback::*)(), &C::operator()>*);
public:
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};
template<typename T>
struct is_callable
: std::conditional<
std::is_class<T>::value,
is_callable_impl<T>,
std::false_type
>::type
{ };
template<typename T> constexpr bool is_callable_v = is_callable<T>::value;
This checks if T
has a member type key_type
.
template<class T, class R = void>
struct enable_if_type { typedef R type; };
template<class T, class Enable = void>
struct is_searchable : std::false_type {};
template<class T>
struct is_searchable<T, typename enable_if_type<typename T::key_type>::type> : std::true_type
{};
template<typename T> constexpr bool is_searchable_v = is_searchable<T>::value;
template <typename T> struct is_vector { static const bool value = false; };
template <class T, class A> struct is_vector<std::vector<T, A>> { static bool const value = true; };
template<typename T>
struct is_container : std::false_type {};
template<typename T>
struct is_container<std::vector<T> > : std::true_type {};
template<typename T>
struct is_container<std::basic_string<T> > : std::true_type {};
template<typename T, int N>
struct is_container<std::array<T,N> > : std::true_type {};