#include <iostream>
#include <variant>
/// This version does not work as I expect.
///
/// Expected program output:
/// A
/// B
/// OTHER
/// OTHER
///
/// Actual program output:
/// OTHER
/// OTHER
/// OTHER
/// OTHER
/// Delta from working version of program:
/// 1. my_visit() only has the const method overload, the non-const version has been commented out.
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
struct A {};
struct B {};
struct C {};
struct D {};
using V = std::variant<A, B, C, D>;
class MyVisitor
{
V v_;
public:
MyVisitor(V &&v) : v_(std::move(v)) {}
/// template <typename ...Args>
/// decltype(auto) my_visit(Args&&... args)
/// {
/// return std::visit(overloaded{std::forward<Args>(args)...}, v_);
/// }
template <typename ...Args>
decltype(auto) my_visit(Args&&... args) const
{
return std::visit(overloaded{std::forward<Args>(args)...}, v_);
}
};
int main()
{
auto const print_a = [](A&) { std::cerr << "A\n"; };
auto const print_b = [](B&) { std::cerr << "B\n"; };
auto const print_o = [](auto&) { std::cerr << "OTHER\n"; };
{
// this prints "A"
V v{A{}};
MyVisitor visitor{std::move(v)};
visitor.my_visit(print_a, print_b, print_o);
}
{
// this prints "B"
V v{B{}};
MyVisitor visitor{std::move(v)};
visitor.my_visit(print_a, print_b, print_o);
}
{
// this prints "OTHER"
V v{C{}};
MyVisitor visitor{std::move(v)};
visitor.my_visit(print_a, print_b, print_o);
}
{
// this prints "OTHER"
V v{D{}};
MyVisitor visitor{std::move(v)};
visitor.my_visit(print_a, print_b, print_o);
}
return 0;
}