#include <algorithm>
#include <catch2/catch_test_macros.hpp>
#include <compare>
#include <concepts>
#include <format>
#include <ios>
#include <iostream>
#include <print>
#include <sstream>
#include <string>
#include <variant>
namespace example_2c {
struct custom {
std::string answer;
};
struct value_has_open_dispatch {};
(
ANY_FN_DEF(
public, std::string, to_string, (),
const,
[&x]() { return std::format("{}", x); }),
ANY_FN_DEF(
public,
void, from_string, (std::string_view), ,
[&x](std::string_view sv) -> void {
std::stringstream ss{std::string{sv},
std::ios_base::in};
ss >> std::boolalpha >> x;
})), )
template <typename Proxy = anyxx::shared>
using vany_value =
using concrete_value = anyxx::vany_type_trait<vany_value<>>::concrete_variant;
using any_in_variant = anyxx::vany_type_trait<vany_value<>>::any_in_variant;
static_assert(
static_assert(
std::same_as<concrete_value, std::variant<bool, int, double, std::string>>);
static_assert(std::same_as<any_in_variant, any_value<anyxx::shared>>);
}
static std::string to_string(custom const& x) {
return "{" + x.answer + "}";
};
static void from_string(custom & x, std::string_view sv) {
x.answer = sv.substr(1, sv.length() - 2);
};
};
TEST_CASE("example 2ca static_ simple variant") {
using namespace example_2c;
using namespace std::string_literals;
using namespace anyxx;
using any_variant =
any_value<using_<std::variant<bool, int, double, std::string>>>;
CHECK(any_variant{true}.to_string() == "true");
CHECK(any_variant{42}.to_string() == "42");
CHECK(any_variant{3.14}.to_string() == "3.14");
CHECK(any_variant{"hello world"s}.to_string() == "hello world"s);
}
TEST_CASE("example 2cb static_ any variant") {
using namespace example_2c;
using namespace std::string_literals;
using namespace anyxx;
static_assert(
constructibile_for<any_value<shared>, vany_value<>::proxy_t>);
vany_value<> vv_custom_43 =
any_value<shared>{std::in_place_type<custom>, "43"};
vany_value<> vv_custom_42 = {
any_value<shared>{std::in_place, custom{"42"}}};
CHECK(vany_value<>{true}.to_string() == "true");
CHECK(vv_custom_42.to_string() == "{42}");
CHECK(vv_custom_43.to_string() == "{43}");
vany_value<anyxx::val> b{true};
static_assert(!anyxx::is_const_data<vany_value<>::proxy_t>);
static_assert(!anyxx::is_const_data<vany_value<anyxx::val>::proxy_t>);
b.from_string("false");
CHECK(b.to_string() == "false");
vany_value<anyxx::val> vv_custom_FS{
any_value<anyxx::val>{std::in_place_type<custom>}};
vv_custom_FS.from_string("{43}");
CHECK(vv_custom_FS.to_string() == "{43}");
}
namespace example_2c {
, vany_stream, vany_value<>,
(void(anyxx::virtual_<any_value<anyxx::shared>>, std::ostream&)),
([](const std::string& s,
std::ostream& os) { os << "String: " << s << ", "; },
[](int i, std::ostream& os) { os << "Int: " << i << ", "; },
[](double d, std::ostream& os) { os << "Double: " << d << ", "; },
[](bool b, std::ostream& os) {
os << "Bool: " << std::boolalpha << b << ", ";
}))
}
namespace example_2c {
auto __ = vany_stream.define<custom>(
[](const custom& c, std::ostream& os) { os << "Custom: " << c.answer; });
}
TEST_CASE("example 2cc static_ any variant single open dispatch") {
using namespace example_2c;
using namespace std::string_literals;
using namespace anyxx;
vany_value<> vv1{std::string{"hello"}};
vany_value<> vv2{int{42}};
vany_value<> vv3{
any_value<shared>{std::in_place_type<custom>, "Hello world!"}};
std::stringstream ss;
vany_stream(vv1, ss);
vany_stream(vv2, ss);
vany_stream(vany_value<>{true}, ss);
vany_stream(vv3, ss);
CHECK(ss.str() == "String: hello, Int: 42, Bool: true, Custom: Hello world!");
}
namespace example_2c {
, vany_compare, vany_value<>,
(std::partial_ordering(anyxx::virtual_<any_value<anyxx::shared>>,
anyxx::virtual_<any_value<anyxx::shared>>)),
([]<typename T>(T&& t, T&& u) -> std::partial_ordering
requires(!anyxx::is_any<T>)
{ return std::forward<T>(t) <=> std::forward<T>(u); },
[](bool lhs, std::integral auto rhs) -> std::partial_ordering {
return lhs <=> static_cast<bool>(rhs);
},
[](std::integral auto lhs, bool rhs) -> std::partial_ordering {
return static_cast<bool>(lhs) <=> rhs;
},
[](bool lhs, bool rhs) -> std::partial_ordering { return lhs <=> rhs; },
[](std::integral auto lhs, std::integral auto rhs)
-> std::partial_ordering { return lhs <=> rhs; },
[](std::floating_point auto lhs, std::floating_point auto rhs)
-> std::partial_ordering { return lhs <=> rhs; }));
auto operator<=>(const vany_value<>& lhs, const vany_value<>& rhs) {
return vany_compare(lhs, rhs);
}
auto operator==(const vany_value<>& lhs, const vany_value<>& rhs) {
return (lhs <=> rhs) == std::weak_ordering::equivalent;
}
auto operator!=(const vany_value<>& lhs, const vany_value<>& rhs) {
return (lhs <=> rhs) != std::weak_ordering::equivalent;
}
auto __ = vany_compare.define<custom, custom>(
[](const auto& lhs, const auto& rhs) -> std::partial_ordering {
return lhs.answer <=> rhs.answer;
});
auto __ = vany_compare.define<concrete_value, custom>(
[](const auto& lhs, const auto& rhs) -> std::partial_ordering {
return anyxx::trait_as<value>(lhs).to_string() <=> rhs.answer;
});
auto __ = vany_compare.define<custom, concrete_value>(
[](const auto& lhs, const auto& rhs) -> std::partial_ordering {
return lhs.answer <=> anyxx::trait_as<value>(rhs).to_string();
});
auto __ = vany_compare.define<concrete_value, concrete_value>(
[](const auto& lhs, const auto& rhs) -> std::partial_ordering {
return anyxx::trait_as<value>(lhs).to_string() <=>
anyxx::trait_as<value>(rhs).to_string();
});
}
TEST_CASE("example 2cd static_ any variant double dispatch") {
using namespace example_2c;
using namespace std::string_literals;
using namespace anyxx;
vany_value<> vv1{"hello"s};
vany_value<> vvbt{bool{true}};
vany_value<> vvbf{bool{false}};
vany_value<> vvi{int{42}};
vany_value<> vvi0{int{0}};
vany_value<> vvf{double{42.0}};
vany_value<> vv3{
any_value<shared>{std::in_place_type<custom>, "Hello world!"}};
vany_value<> vv4{
any_value<shared>{std::in_place_type<custom>, "hello"}};
bool x = vany_compare(vv1, vv1) == std::partial_ordering::equivalent;
CHECK(x);
auto y = vv1 <=> vv1;
CHECK(y == std::weak_ordering::equivalent);
auto z = vv1 == vv1;
CHECK(z);
CHECK(vv3 == vv3);
CHECK(vv3 != vv1);
CHECK("hello"s > "Hello world!"s);
CHECK(vv1 > vv3);
CHECK(vv3 != vv4);
CHECK(vv1 == vv4);
CHECK(vvi == vvf);
CHECK(vvbt != vvbf);
CHECK(vvi != vvbf);
CHECK(vvi == vvbt);
CHECK(vvi0 == vvbf);
}
C++ header only library for external polymorphism.
Any< using_< vany_variant< Any, Proxy, Types... > > > make_vany
A factory type to direct get the any for the vany.
Definition anyxx.hpp:1784
Requirements for a proxy type.
Definition anyxx.hpp:1491
#define ANY_MODEL_MAP(model_, trait_)
ANY_MODEL_MAP macro.
Definition anyxx.hpp:1192
std::variant< Any< Proxy >, Types... > vany_variant
Definition anyxx.hpp:1780
#define ANY(n, l,...)
Simple ANY macro.
Definition anyxx.hpp:884
#define ANY_FN_DEF(access, ret, name, params, const_,...)
TRAIT function with default behavior.
Definition anyxx.hpp:998
#define VANY_DISPACH_DECLARE(export_, name, vany, signature, static_dispatch)
Declare a singleton object for open vany dispatch.
Definition anyxx.hpp:4256
#define VANY_DISPACH(namespace_, name)
Define a vany dispatch singleton object in a source file.
Definition anyxx.hpp:4274
Definition anyxx.hpp:3116