1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#include <iostream>
#include <type_traits>
#include <string>
#include <memory>
namespace Utility {
enum UnaryPredicate {IsString, IsPointer}; // etc...
template <int N, typename A> struct UnaryCondition;
template <typename A>
struct UnaryCondition<IsString, A> {static constexpr std::size_t value = std::is_same<A, std::string>::value;};
template <typename A>
struct UnaryCondition<IsPointer, A> {static constexpr std::size_t value = std::is_pointer<A>::value;};
template <int, typename...> struct count_unary_true;
template <int N, typename A>
struct count_unary_true<N, A> {
static constexpr std::size_t value = UnaryCondition<N, A>::value;
};
template <int N, typename FIRST, typename... REST>
struct count_unary_true<N, FIRST, REST...> {
static constexpr std::size_t value = count_unary_true<N, FIRST>::value + count_unary_true<N, REST...>::value;
};
// --------------------------------------------------------------------------------------------------------------------------
enum BinaryPredicate {IsConvertible, IsBaseOf}; // etc...
template <int N, typename A, typename B> struct BinaryCondition;
template <typename A, typename B>
struct BinaryCondition<IsConvertible, A, B> {static constexpr std::size_t value = std::is_convertible<A,B>::value;};
template <typename A, typename B>
struct BinaryCondition<IsBaseOf, A, B> {static constexpr std::size_t value = std::is_base_of<A,B>::value;};
template <int, typename, typename...> struct count_binary_true;
template <int N, typename A, typename B>
struct count_binary_true<N, A, B> {
static constexpr std::size_t value = BinaryCondition<N, A, B>::value;
};
template <int N, typename A, typename FIRST, typename... REST>
struct count_binary_true<N, A, FIRST, REST...> {
static constexpr std::size_t value = count_binary_true<N, A, FIRST>::value + count_binary_true<N, A, REST...>::value;
};
// --------------------------------------------------------------------------------------------------------------------------
template <bool CONDITION>
struct true_if : std::conditional<CONDITION, std::true_type, std::false_type>::type {};
template <int N, typename... T>
struct all_unary_true : true_if<count_unary_true<N, T...>::value == (sizeof...(T))> {};
template <int N, typename... T>
struct all_binary_true : true_if<count_binary_true<N, T...>::value == (sizeof...(T) - 1)> {};
}
template <typename... TYPES>
typename std::enable_if<Utility::all_binary_true<Utility::IsConvertible, int, TYPES...>::value>::type foo (TYPES&&...) {
std::cout << "All are implicitly convertible to int." << std::endl;
}
struct Thing{};
template <typename... TYPES>
typename std::enable_if<Utility::all_binary_true<Utility::IsBaseOf, const Thing&, TYPES...>::value>::type foo (TYPES&&...) {
std::cout << "All are derived from Thing." << std::endl;
}
template <typename... TYPES>
typename std::enable_if<Utility::all_unary_true<Utility::IsString, TYPES...>::value>::type foo (TYPES&&...) {
std::cout << "All are strings." << std::endl;
}
template <typename... TYPES>
typename std::enable_if<Utility::all_unary_true<Utility::IsPointer, TYPES...>::value>::type foo (TYPES&&...) {
std::cout << "All are pointers." << std::endl;
}
|