Created
August 8, 2020 00:59
-
-
Save willkill07/428f248a7ff303ae672b0332ce419891 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Prevent warning when testing the Abstract test type. | |
#include <type_traits> | |
template <typename...> | |
struct voider { | |
using type = void; | |
}; | |
template<typename ... Ts> | |
using void_t = typename voider<Ts...>::type; | |
template<class T> | |
struct type_identity { | |
using type = T; | |
}; | |
template<class T> | |
using type_identity_t = typename type_identity<T>::type; | |
namespace detail | |
{ | |
template<class Default, | |
class AlwaysVoid, | |
template<class...> | |
class Op, | |
class... Args> | |
struct detector : type_identity<Default> | |
{ | |
using value_t = std::false_type; | |
}; | |
template<class Default, template<class...> class Op, class... Args> | |
struct detector<Default, void_t<Op<Args...>>, Op, Args...> | |
: type_identity<Op<Args...>> | |
{ | |
using value_t = std::true_type; | |
}; | |
} // namespace detail | |
struct nonesuch | |
{ | |
nonesuch() = delete; | |
~nonesuch() = delete; | |
nonesuch(nonesuch const&) = delete; | |
nonesuch& operator=(nonesuch const&) = delete; | |
nonesuch(nonesuch &&) = delete; | |
nonesuch& operator=(nonesuch &&) = delete; | |
}; | |
template<template<class...> class Op, class... Args> | |
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t; | |
template<template<class...> class Op, class... Args> | |
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type; | |
template<class Default, template<class...> class Op, class... Args> | |
using detected_or = detail::detector<Default, void, Op, Args...>; | |
template<template<class...> class Op, class... Args> | |
constexpr bool is_detected_v = is_detected<Op, Args...>::value; | |
template<class Default, template<class...> class Op, class... Args> | |
using detected_or_t = typename detected_or<Default, Op, Args...>::type; | |
template<class Expected, template<class...> class Op, class... Args> | |
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; | |
template<class Expected, template<class...> class Op, class... Args> | |
constexpr bool is_detected_exact_v | |
= is_detected_exact<Expected, Op, Args...>::value; | |
template<class To, template<class...> class Op, class... Args> | |
using is_detected_convertible | |
= std::is_convertible<detected_t<Op, Args...>, To>; | |
template<class To, template<class...> class Op, class... Args> | |
constexpr bool is_detected_convertible_v | |
= is_detected_convertible<To, Op, Args...>::value; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment