Created
December 30, 2022 17:38
-
-
Save ttldtor/dca64c8c34735d87839fdea2f8c0e9a1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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