Skip to content

Instantly share code, notes, and snippets.

@ttldtor
Created December 30, 2022 17:38
Show Gist options
  • Save ttldtor/dca64c8c34735d87839fdea2f8c0e9a1 to your computer and use it in GitHub Desktop.
Save ttldtor/dca64c8c34735d87839fdea2f8c0e9a1 to your computer and use it in GitHub Desktop.
#include <boost/variant.hpp>
#include <boost/variant2.hpp>
#include <iostream>
#include <memory>
#include <mutex>
#include <type_traits>
#include <variant>
struct Error {};
template<template<typename...> typename Variant>
struct Session {
struct Context {};
Context ctx;
std::recursive_mutex mtx;
explicit Session() : ctx{}, mtx{} {
}
template<typename F>
auto run(F &&f) -> Variant<decltype(std::invoke(std::forward<F>(f), std::forward<Context>(ctx))), Error> {
std::lock_guard lock(mtx);
return std::invoke(std::forward<F>(f), std::forward<Context>(ctx));
}
};
template<typename T>
std::size_t getId() {
static std::size_t id = 0;
return id++;
}
struct Traceable {
const std::size_t id{};
std::size_t data{};
explicit Traceable(std::size_t data = 0) : id{getId<Traceable>()}, data{data} {
std::cout << "Traceable(data = " << data << "){id = " << id << "}\n";
}
Traceable(const Traceable &t) : id{getId<Traceable>()}, data{t.data} {
std::cout << "Traceable(const&" + t.toString() + ")\n";
}
Traceable &operator=(const Traceable &t) {
std::cout << toString() + " = const&" + t.toString() + "\n";
data = t.data;
return *this;
}
Traceable(Traceable &&t) noexcept : id{getId<Traceable>()} {
std::cout << "Traceable(&&" + t.toString() + ")\n";
std::swap(data, t.data);
}
Traceable &operator=(Traceable &&t) noexcept {
std::cout << toString() + " = &&" + t.toString() + "\n";
std::swap(data, t.data);
return *this;
}
~Traceable() {
std::cout << "~" + toString() + "\n";
}
static std::string toString(std::size_t id, std::size_t data) {
return std::string("Traceable{id = ") + std::to_string(id) + ", data = " + std::to_string(data) + "}";
}
[[nodiscard]] std::string toString() const {
return toString(id, data);
}
template<typename OutputStream>
friend OutputStream &operator<<(OutputStream &os, const Traceable &t) {
os << t.toString();
return os;
}
};
template<template<typename...> typename Variant, typename TraceableT, typename Name, typename Visit>
auto test(Name &&name, Visit &&visit) {
std::cout << "\nTest \"" << name << "\":\n-----------------------------------------\n";
Session<Variant> s{};
auto r = std::invoke(
std::forward<Visit>(visit),
[]<typename T>(T &&v) {
if constexpr (std::is_same_v<T, Error>) {
return TraceableT{};
} else {
return v;
}
},
s.run([](auto &&/*ctx*/) {
TraceableT traceable{42};
traceable = TraceableT{1};
return traceable;
}));
std::cout << "-> " << r << "\n";
}
template<template<typename...> typename Variant, typename TraceableT, typename Name, typename Visit>
auto test2(Name &&name, Visit &&visit) {
std::cout << "\nTest2 \"" << name << "\":\n-----------------------------------------\n";
Session<Variant> s{};
auto r = std::invoke(
std::forward<Visit>(visit),
[]<typename T>(T &&v) {
if constexpr (std::is_same_v<T, Error>) {
return std::make_unique<TraceableT>();
} else {
return v;
}
},
s.run([](auto &&/*ctx*/) {
auto traceable = std::make_unique<TraceableT>(42);
traceable = std::make_unique<TraceableT>(1);
return traceable;
}));
std::cout << " -> " << *r << "\n";
}
int main() {
test<std::variant, Traceable>("std::variant", []<typename... Ts>(Ts &&...params) {
return std::visit(std::forward<Ts>(params)...);
});
test<boost::variant, Traceable>("boost::variant", []<typename... Ts>(Ts &&...params) {
return boost::apply_visitor(std::forward<Ts>(params)...);
});
test<boost::variant2::variant, Traceable>("boost::variant2::variant", []<typename... Ts>(Ts &&...params) {
return boost::variant2::visit(std::forward<Ts>(params)...);
});
test2<std::variant, Traceable>("std::variant", []<typename... Ts>(Ts &&...params) {
return std::visit(std::forward<Ts>(params)...);
});
test2<boost::variant, Traceable>("boost::variant", []<typename... Ts>(Ts &&...params) {
return boost::apply_visitor(std::forward<Ts>(params)...);
});
test2<boost::variant2::variant, Traceable>("boost::variant2::variant", []<typename... Ts>(Ts &&...params) {
return boost::variant2::visit(std::forward<Ts>(params)...);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment