6FA27FLNKYSKFHX7IJTITDYWHUYYFYDEYF24SPWZF22OXCGLI3EAC
template <typename _T, typename _V, _V(_T::*_method)()>
struct Term<_method> {
using Operand = _T;
// Single item: function of _T.
template <typename _T, typename _R, _R(*_function)(_T &)>
struct Term<_function> {
using Operand = std::decay_t<_T>;
using Result = std::decay_t<_R>;
static constexpr
_V const &get(Operand &operand) {
return (operand.*_method)();
constexpr
Result const &operator()(Operand const &operand) const {
return _function(operand);
}
constexpr
Result const &operator()(Operand &operand) const {
return _function(operand);
template <typename _T, typename _V, _V(_T::*_method)() const>
struct Term<_method> {
using Operand = _T;
// Multiple items: recursively forward the result of the first term to the remaining ones.
template <auto _head, auto ..._tail>
struct Term<_head, _tail...> {
using Operand = std::decay_t<typename Term<_head>::Operand>;
using Result = typename Term<_tail...>::Result;
static constexpr
_V const &get(Operand const &operand) {
return (operand.*_method)();
constexpr
Result const &operator()(Operand const &operand) const {
return Term<_tail...>{}(Term<_head>{}(operand));
}
constexpr
Result const &operator()(Operand &operand) const {
return Term<_tail...>{}(Term<_head>{}(operand));
template <typename _T, typename _V, _V(*_function)(_T const &)>
struct Term<_function> {
using Operand = _T;
template <auto ..._l, auto ..._r>
constexpr
Equal<Term<_l ...>, Term<_r ...>> operator==(Term<_l ...>, Term<_r ...>) {
return {};
}
// std::get helper
namespace detail {
template <std::size_t, typename>
struct std_get_f;
static constexpr
bool test(L const &l, R const &r) {
return _L::get(l) == _R::get(r);
}
template <auto ..._constraints>
struct Constraints {
static_assert((std::is_same_v<bool, typename std::decay_t<decltype(_constraints)>::Result> && ...));
using Minterm = std::bitset<sizeof...(_constraints)>;
struct Aggregate {
Foo foo;
Bar bar;
};
constexpr
auto aggFooValue =
Term<&Aggregate::foo, &Foo::value>{};
constexpr
auto aggBarValue =
Term<&Aggregate::bar, &Bar::value>{};
constexpr
auto fooEqBar =
aggFooValue == aggBarValue;
// Pair of Foo
using FooFoo = std::pair<Foo, Foo>;
constexpr
auto fooEqFoo =
Term<&FooFoo::first, &Foo::value>{} == Term<&FooFoo::second, &Foo::value>{};
// Tuple of Foo
using FooFooFoo = std::tuple<Foo, Foo, Foo>;
constexpr
auto fooEqFoo2 =
Term<std_get<0, FooFooFoo>, &Foo::value>{} == Term<std_get<1, FooFooFoo>, &Foo::value>{};
//
// Main
//