7OON6I5DETIRCQ24MOUVJ5QWQIMPTNP2PCRAA3BFOUMZ3I6PZOKQC template <auto ...>struct Term;// Single item: field (member or method) of _T.template <typename _T, typename _R, _R(_T::*_field)>struct Term<_field> {using Operand = std::decay_t<_T>;using Result = std::decay_t<std::conditional_t<std::is_function_v<_R>,std::invoke_result_t<decltype(_field), _T>,_R>>;constexprResult const &operator()(Operand const &operand) const {if constexpr (std::is_function_v<_R>) {return (operand.*_field)();} else {return operand.*_field;}}};// 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>;constexprResult const &operator()(Operand const &operand) const {return _function(operand);}constexprResult const &operator()(Operand &operand) const {return _function(operand);}};// 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;constexprResult const &operator()(Operand const &operand) const {return Term<_tail...>{}(Term<_head>{}(operand));}constexprResult const &operator()(Operand &operand) const {return Term<_tail...>{}(Term<_head>{}(operand));}};
template <auto ..._constraints>
namespace detail {template <typename ..._Terms> struct operand_f;template <typename ..._Terms> using Operand = typename operand_f<_Terms...>::value;template <typename _Head, typename ..._Tail>struct operand_f<_Head, _Tail...> {using value = typename _Head::Operand;};} // namespace detailtemplate <typename ..._Terms>
static_assert((std::is_same_v<bool, typename std::decay_t<decltype(_constraints)>::Result> && ...));using Minterm = std::bitset<sizeof...(_constraints)>;};
static_assert((std::is_same_v<bool, typename std::decay_t<_Terms>::Result> && ...),"All Constraints must have a Result type of bool");using Operand = detail::Operand<_Terms...>;using Minterm = std::bitset<sizeof...(_Terms)>;template <std::size_t _bit, typename _Head, typename ..._Tail>constexprvoid populate(Minterm &minterm, Operand const &operand, List<_Head, _Tail...>) const {minterm[_bit] = _Head{}(operand);if constexpr (sizeof...(_Tail)) {populate<_bit + 1>(minterm, operand, List<_Tail...>{});}}
constexprauto fooBarOdd =Constraints<Term<&Aggregate::foo, &Foo::value, isOdd>,Term<&Aggregate::bar, &Bar::value, isEven>>{};//// Assertions//template <typename _Term>struct TermClosure {_Term term;typename _Term::Operand operand;};template <typename ..._Terms>bool check(_Terms &&...terms) {return (std::get<0>(terms)(std::get<1>(terms)) && ...);}
std::cout << Term<&Foo::value, isOdd>{}(foo) << '\n';for (int i = 0; i < 10; ++i) {std::cout << i << ": " << fooBarOdd(Aggregate{Foo{"foo", i}, Bar{i >> 1}}) << '\n';}std::cout << check(std::make_tuple(Term<&Foo::value, isEven>{}, Foo{"foo", 0}),std::make_tuple(Term<&Foo::value, isOdd >{}, Foo{"foo", 1}),std::make_tuple(Term<&Foo::value, isEven>{}, Foo{"foo", 2}),std::make_tuple(Term<&Foo::value, isOdd >{}, Foo{"foo", 3}),std::make_tuple(Term<&Foo::value, isEven>{}, Foo{"foo", 4}),std::make_tuple(Term<&Foo::value, isOdd >{}, Foo{"foo", 5}),std::make_tuple(Term<&Foo::value, isEven>{}, Foo{"foo", 6}),std::make_tuple(Term<&Foo::value, isOdd >{}, Foo{"foo", 7}),std::make_tuple(Term<&Foo::value, isEven>{}, Foo{"foo", 8}),std::make_tuple(Term<&Foo::value, isOdd >{}, Foo{"foo", 9}),std::make_tuple(Term<&Foo::value, isEven>{}, Foo{"foo", 10})) << '\n';
: 1name: cpp-genversion: 0.0.1summary: C++ constraint based generator.type: exelanguage: c++project: cpp-genlicense: MIT
#pragma once#include <type_traits>template <auto ...>struct Term;// Single item: field (member or method) of _T.template <typename _T, typename _R, _R(_T::*_field)>struct Term<_field> {using Operand = std::decay_t<_T>;using Result = std::conditional_t<std::is_function_v<_R>,std::invoke_result_t<decltype(_field), _T>,_R const &>;constexprResult operator()(Operand const &operand) const {if constexpr (std::is_function_v<_R>) {return (operand.*_field)();} else {return operand.*_field;}}};// Single item: function of _T.template <typename _T, typename _R, _R(*_function)(_T &)>struct Term<_function> {using Operand = std::decay_t<_T>;using Result = _R;constexprResult operator()(Operand const &operand) const {return _function(operand);}constexprResult operator()(Operand &operand) const {return _function(operand);}};// 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;constexprResult operator()(Operand const &operand) const {return Term<_tail...>{}(Term<_head>{}(operand));}constexprResult operator()(Operand &operand) const {return Term<_tail...>{}(Term<_head>{}(operand));}};
using cxxcxx.poptions += "-I$src_root/include/"cxx.coptions += "-Wall" "-Werror"exe{main} : cxx{src/main.cpp} hxx{include/cpp-gen/Term.h}