Any++
Loading...
Searching...
No Matches
_2b_trait_monoid.cpp

A self referntial trait that models a monoid. Show how to use a MODEL_MAP that acts simultanious as runtime and complitem customization point

#include <algorithm>
#include <bit_factory/anyxx_range.hpp>
#include <catch2/catch_test_macros.hpp>
#include <list>
#include <print>
#include <string>
#include <vector>
namespace anyxx {
//
} // namespace anyxx
namespace example_2b {
TRAIT_EX(monoid,
(ANY_FN_DEF(public, anyxx::self, id, (), const, []() { return T{}; }),
ANY_FN_DEF(public, anyxx::self, op, (anyxx::self const&), const,
[&x](auto const& r) {
std::println("op-default {}", typeid(T).name());
auto self = anyxx::trait_as<monoid>(x);
return get_proxy(self.concat(
std::vector{anyxx::trait_as<monoid>(r)})); // NOLINT
}),
ANY_FN_DEF(public, anyxx::self, concat,
((anyxx::any_forward_range<anyxx::self, anyxx::self,
anyxx::cref> const&)),
const,
[&x](const auto& r) {
std::println("concat-default {}", typeid(T).name());
auto self = anyxx::trait_as<monoid>(x);
return get_proxy(std::ranges::fold_left(
r | std::views::transform([](auto const& y) {
return anyxx::trait_as<monoid>(y);
}),
self, [&](auto const& m1, auto const& m2) {
return m1.op(m2);
}));
}),
ANY_OP_DEF(public, bool, ==, eq, (anyxx::self const&), const,
([&x](auto const& r) { return x == r; }))),
, , ())
template <typename Box = anyxx::val>
using any_monoid = anyxx::any<Box, monoid>;
} // namespace example_2b
ANY_MODEL_MAP((int), example_2b::monoid) {
static int concat(int self, auto const& r) {
std::println("concat {}", typeid(int).name());
return std::ranges::fold_left(r, self,
[&](int m1, int m2) { return m1 + m2; });
};
};
ANY_MODEL_MAP((std::string), example_2b::monoid) {
static std::string op(std::string const& self, std::string const& r) {
std::println("op {}", typeid(std::string).name());
return self + r;
};
};
namespace example_2b {
template <anyxx::is_any Monoid>
void test_monoid_traited(
Monoid const& m, anyxx::any_forward_range<Monoid, Monoid, anyxx::cref>& r);
template <typename P1>
requires(!anyxx::is_any<P1>)
void test_monoid(P1 const& p1, std::ranges::forward_range auto const& r) {
using any_monoid = typename anyxx::using_<P1>::template as<monoid>;
test_monoid_traited<any_monoid>(any_monoid{p1}, r);
}
template <anyxx::is_any Monoid>
void test_monoid(
Monoid const& m,
anyxx::any_forward_range<Monoid, Monoid, anyxx::cref> const& r) {
test_monoid_traited<Monoid>(m, r);
}
template <anyxx::is_any Monoid>
void test_monoid_traited(
Monoid const& m,
anyxx::any_forward_range<Monoid, Monoid, anyxx::cref> const& r) {
auto id = m.id();
using type_1 = decltype(m.op(id.op(m)));
using type_2 = decltype(m.op(m.op(id)));
static_assert(std::same_as<type_1, type_2>);
static_assert(std::same_as<type_1, Monoid>);
auto c1 = m.op(id.op(m)) == m.op(m.op(id));
CHECK(c1);
auto c2 = (m.concat(r)) ==
std::ranges::fold_left(
r, m, [&](Monoid const& m1, [[maybe_unused]] Monoid const& m2) {
return m1.op(m2);
});
CHECK(c2);
}
anyxx::any_forward_range<any_monoid<anyxx::val>, any_monoid<anyxx::val>,
anyxx::val>
make_a_range(bool use_list) {
using namespace std::string_literals;
if (use_list)
return std::list<any_monoid<anyxx::val>>{{"2"s}, {"3"s}};
else
return std::vector<any_monoid<anyxx::val>>{{"2"s}, {"3"s}};
}
// struct not_mappepd{ int v; };
} // namespace example_2b
//
TEST_CASE("example 2b monoid simple") {
example_2b::any_monoid<anyxx::using_<int>> x{2};
example_2b::any_monoid<anyxx::using_<int>> y{x};
example_2b::any_monoid<anyxx::using_<int>> z = y;
CHECK(get_proxy_value(z) == 2);
example_2b::any_monoid<anyxx::using_<int>> a{std::move(x)};
CHECK(get_proxy_value(a) == 2);
static_assert(anyxx::is_proxy<decltype(x)::proxy_t>);
static_assert(anyxx::is_any<decltype(x)>);
static_assert(
anyxx::moveable_from<decltype(x)::proxy_t, decltype(y)::proxy_t>);
static_assert(
!anyxx::borrowable_from<decltype(x)::proxy_t, decltype(y)::proxy_t,
decltype(y)::v_table_t>);
}
TEST_CASE("example 2b monoid a") {
using namespace example_2b;
using namespace std::string_literals;
using namespace anyxx;
test_monoid((1), std::vector{2, 3});
test_monoid<any<using_<int>, monoid>>(
trait_as<monoid>(1), std::vector<any<using_<int>, monoid>>{{2}, {3}});
// test_monoid(not_mappepd{1}, std::vector{not_mappepd{2}, not_mappepd{3}});
}
TEST_CASE("example 2b monoid b") {
using namespace example_2b;
using namespace std::string_literals;
using namespace anyxx;
test_monoid("1"s, std::vector{"2"s, "3"s});
test_monoid<using_<std::string>::as<monoid>>(
trait_as<monoid>("1"s),
std::vector<using_<std::string>::as<monoid>>{{"2"s}, {"3"s}});
}
TEST_CASE("example 2b monoid c") {
using namespace example_2b;
using namespace std::string_literals;
using namespace anyxx;
test_monoid<any_monoid<anyxx::val>>("1"s, make_a_range(true));
} // NOLINT
TEST_CASE("example 2b monoid d") {
using namespace example_2b;
using namespace std::string_literals;
using namespace anyxx;
test_monoid<any_monoid<anyxx::val>>("1"s, make_a_range(false));
}
C++ header only library for external polymorphism.
#define ANY_OP_DEF(access, ret, op, name, params, const_,...)
TRAIT operator with default behavior.
Definition anyxx.hpp:1066
#define ANY_MODEL_MAP(model_, trait_)
ANY_MODEL_MAP macro.
Definition anyxx.hpp:1192
observer< const_void > cref
Definition anyxx.hpp:1863
#define TRAIT_EX(n,...)
TRAIT with decoration.
Definition anyxx.hpp:782
#define ANY_FN_DEF(access, ret, name, params, const_,...)
TRAIT function with default behavior.
Definition anyxx.hpp:998