Skip to content

Instantly share code, notes, and snippets.

@utilForever
Last active September 28, 2018 02:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save utilForever/824a1bcb3a6b589b1c887e7ede930976 to your computer and use it in GitHub Desktop.
Save utilForever/824a1bcb3a6b589b1c887e7ede930976 to your computer and use it in GitHub Desktop.
C++17 overload pattern with std::variant and std::visit (https://www.bfilipek.com/2018/09/visit-variants.html)
#include <iostream>
#include <variant>
struct Fluid { };
struct LightItem { };
struct HeavyItem { };
struct FragileItem { };
struct GlassBox { };
struct CardboardBox { };
struct ReinforcedBox { };
struct AmortisedBox { };
struct VisitPackage
{
void operator()(Fluid&) { std::cout << "fluid\n"; }
void operator()(LightItem&) { std::cout << "light item\n"; }
void operator()(HeavyItem&) { std::cout << "heavy item\n"; }
void operator()(FragileItem&) { std::cout << "fraile\n"; }
};
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
int main()
{
std::variant<Fluid, LightItem, HeavyItem, FragileItem> package;
std::visit(VisitPackage(), package);
std::visit(overload{
[](Fluid&) { std::cout << "fluid\n"; },
[](LightItem&) { std::cout << "light item\n"; },
[](HeavyItem&) { std::cout << "heavy item\n"; },
[](FragileItem&) { std::cout << "fraile\n"; }
}, package);
std::variant<LightItem, HeavyItem> basicPackA;
std::variant<LightItem, HeavyItem> basicPackB;
std::visit(overload{
[](LightItem&, LightItem&) { std::cout << "2 light items\n"; },
[](LightItem&, HeavyItem&) { std::cout << "light & heavy items\n"; },
[](HeavyItem&, LightItem&) { std::cout << "heavy & light items\n"; },
[](HeavyItem&, HeavyItem&) { std::cout << "2 heavy items\n"; },
}, basicPackA, basicPackB);
std::variant<Fluid, LightItem, HeavyItem, FragileItem> item { Fluid() };
std::variant<GlassBox, CardboardBox, ReinforcedBox, AmortisedBox> box { CardboardBox() };
std::visit(overload{
[](Fluid&, GlassBox&) { std::cout << "fluid in a glass box\n"; },
[](Fluid&, auto) { std::cout << "warning! fluid in a wrong container!\n"; },
[](LightItem&, CardboardBox&) { std::cout << "a light item in a cardboard box\n"; },
[](LightItem&, auto) { std::cout << "a light item can be stored in any type of box, but cardboard is good enough\n"; },
[](HeavyItem&, ReinforcedBox&) { std::cout << "a heavy item in a reinforced box\n"; },
[](HeavyItem&, auto) { std::cout << "warning! a heavy item should be stored in a reinforced box\n"; },
[](FragileItem&, AmortisedBox&) { std::cout << "fragile item in an amortised box\n"; },
[](FragileItem&, auto) { std::cout << "warning! a fragile item should be stored in an amortised box\n"; },
}, item, box);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment