Home

Awesome

visit

A fast, generalized, and not quite std conforming, version of visit for variant

This is the implementation for the visit written about in the blog post When performance guarantees hurts performande - std::visit

The reason it is fast is because it does away with the requirement of O(1) lookup, essentially requiring calls through function pointers, and instead allows perfect inlining through a series of if/else, which the compiler can optimise better.

It is generalized in the way that it supports parameters that are not variants, and they are just forwarded to the visitor, as-is. All variant parameters are forwarded as their current member (if any). It also handles types inheriting from std::variant<> as variants.

Example:

using V = std::variant<int, std::string>;
struct S : V
{
  using V::V;
};
using P = std::unique_ptr<int>;
using std::to_string;
using std::string;
struct visitor {
  auto operator()(int i1, P p, int i2) const       { return to_string(i1) + to_string(*p) + to_string(i2); }
  auto operator()(string s, P p, int i2) const     { return s + to_string(*p) + to_string(i2); }
  auto operator()(int i1, P p, string s) const     { return to_string(i1) + to_string(*p) + s; }
  auto operator()(string s1, P p, string s2) const { return s1 + to_string(*p) + s2; }
};

auto r = rollbear::visit(visitor{}, V{1}, std::make_unique<int>(3), S{string{"foo"}});
assert(r == "13foo");

See the test sources for more details.

A note on performance:

The overheads mentioned are tiny, and often other performance factors wil dominate. With that said, the included benchmark program shows that, on my machines, rollbear::visit is consistently faster than std::visit with clang compilers, regardless of whether using libc++ or libstdc++. With gcc compilers it varies with version, and std::visit is typically faster for large variants with many members, while rollbear::visit is typically faster for variants with 8 or fewer members. Measure to find out for your tools and your hardware.

See also Michael Park's variant with its visit. https://github.com/mpark/variant