Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <iostream>
- #include <concepts>
- #include <type_traits>
- // Util
- template<typename T, template<typename...> typename TTemplate >
- struct is_specialization : std::false_type { };
- template<template<typename...> typename Template, typename... TArgs>
- struct is_specialization<Template<TArgs...>, Template> : std::true_type { };
- template<typename T, template<typename...> typename Template>
- constexpr bool is_specialization_v = is_specialization<T, Template>::value;
- template<typename T, template<typename...> typename Template>
- concept specialization = is_specialization_v<T, Template>;
- // Visitor
- namespace visitor
- {
- template<typename T, std::invocable<const T&> F>
- struct when_t {
- using value_t = T;
- F f;
- };
- template<typename T, std::invocable<const T&> F>
- constexpr when_t<T, F> when(F&& f) {
- return when_t<T, F>{ std::forward<F>(f) };
- }
- template<std::invocable<> F>
- struct when_unknown_t {
- F f;
- bool operator()() const {
- f();
- return true;
- }
- };
- template<std::invocable<> F>
- constexpr when_unknown_t<F> when_unknown(F&& f) {
- return when_unknown_t<F>{ std::forward<F>(f) };
- }
- template<typename Base, std::invocable<> Fo, specialization<when_t>... Ws>
- auto make(const when_unknown_t<Fo>& whenunk, Ws&&... whens) {
- constexpr auto make_impl = []<std::derived_from<Base> T>(const Base* t, std::invocable<const T&> auto&& f){
- const T* tc = dynamic_cast<const T*>(t);
- if(tc == nullptr) {
- return false;
- }
- f(*tc);
- return true;
- };
- return [&make_impl, &whenunk, ...whens = std::forward<Ws>(whens)](const Base& t){
- (make_impl.template operator()<typename Ws::value_t>(&t, whens.f) || ... || whenunk());
- };
- }
- }
- // Example
- struct Token {
- virtual ~Token() {}
- };
- struct Optok : Token {
- void optok() const { std::cout << "optok\n"; }
- };
- struct Litok : Token {
- void litok() const { std::cout << "litok\n"; }
- };
- struct Vatok : Token {
- void vatok() const { std::cout << "vatok\n"; }
- };
- struct Hztok : Token {};
- int main() {
- std::vector<Token*> toks(4);
- toks[0] = new Vatok;
- toks[1] = new Litok;
- toks[2] = new Optok;
- toks[3] = new Hztok;
- auto token_visitor = visitor::make<Token>(
- visitor::when_unknown([](){ std::cout << "unknown\n"; }),
- visitor::when<Optok>([](const Optok& op){ op.optok(); }),
- visitor::when<Litok>([](const Litok& li){ li.litok(); }),
- visitor::when<Vatok>([](const Vatok& va){ va.vatok(); })
- );
- for(auto tok : toks)
- token_visitor(*tok);
- return 0;
- }
- // output:
- // vatok
- // litok
- // optok
- // unknown
Add Comment
Please, Sign In to add comment