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 84 85 86 87 88 89 90 91 92 93
|
#include <iostream>
#include <tuple>
#include <type_traits>
#include <vector>
using namespace std;
template<class T, typename... Args>
decltype(void(T{ std::declval<Args>()... }), std::true_type())
test_is_braces_constructible(int);
template<class T, typename... Args>
std::false_type
test_is_braces_constructible(...);
template<class T, typename... Args>
struct is_braces_constructible
{
static constexpr bool value = std::is_same_v<decltype(test_is_braces_constructible<T, Args...>(0)), std::true_type>;
};
struct any_type {
template<class T>
constexpr operator T();// non explicit
};
template<typename T, typename... Args>
struct fits_brace_init_exactly
{
static constexpr bool value = is_braces_constructible<T, Args...>::value && !is_braces_constructible<T, Args..., any_type>::value;
};
enum class enabler_t {};
template<typename T>
using EnableIf = typename std::enable_if<T::value, enabler_t>::type;
template<typename T>
static auto to_tuple(T& object, EnableIf< fits_brace_init_exactly<T, any_type, any_type, any_type, any_type> > = {}) noexcept
{
auto&[p1, p2, p3, p4] = object;
return std::forward_as_tuple(p1, p2, p3, p4);
}
template<typename T>
static auto to_tuple(T& object, EnableIf< fits_brace_init_exactly<T, any_type, any_type, any_type, any_type, any_type> > = {}) noexcept
{
auto&[p1, p2, p3, p4, p5] = object;
return std::forward_as_tuple(p1, p2, p3, p4, p5);
}
template<typename T>
static auto to_tuple(T& object, EnableIf< fits_brace_init_exactly<T, any_type, any_type, any_type, any_type, any_type, any_type> > = {}) noexcept
{
auto&[p1, p2, p3, p4, p5, p6] = object;
return std::forward_as_tuple(p1, p2, p3, p4, p5, p6);
}
template<typename LHS, typename RHS, typename F>
static auto memberwise_operation(LHS& lhs, RHS& rhs, const F& func)
{
auto lhs_tuple = to_tuple(lhs);
auto rhs_tuple = to_tuple(rhs);
return func(lhs_tuple, rhs_tuple);
}
int main()
{
struct Obj
{
double one;
int two;
char three;
std::string four;
const float five;
std::vector<int> six;
};
auto test_obj = Obj{ 1, 1, 1, "whatever", 1,{ 1 } };
{
auto rhs = test_obj;
bool less_than = memberwise_operation(test_obj, rhs, [](auto&lhs, auto&rhs) {return lhs < rhs; });
bool greater_than = memberwise_operation(test_obj, rhs, [](auto&lhs, auto&rhs) {return lhs > rhs; });
cout << less_than << ' ' <<greater_than<< endl;
rhs.four = "zzzzzzzz";
less_than = memberwise_operation(test_obj, rhs, [](auto&lhs, auto&rhs) {return lhs < rhs; });
greater_than = memberwise_operation(test_obj, rhs, [](auto&lhs, auto&rhs) {return lhs > rhs; });
cout << less_than << ' ' <<greater_than<< endl;
}
return 0;
}
|