std::visit a std::variant with overloaded free-function instead of function-object

2k Views Asked by At

In C++17 is there a simple way to std::visit a variant with an overloaded free-function or must I use an object with an overloaded call operator?

In other words, is it possible to add something simple to make the following //ERROR! line compile to be functionally the same as the //OK! line?

#include<variant>
#include<iostream>
#include<list>

#include <boost/hana/functional/overload.hpp>
using boost::hana::overload;

struct A {};
struct B {};

void foo(A) { std::cout << "Got an A!\n"; }
void foo(B) { std::cout << "Got a  B!\n"; }

using AorB = std::variant<A,B>;

constexpr auto foo_obj = overload(
    [](A){std::cout << "Got an A!\n";},
    [](B){std::cout << "Got a  B!\n";});

int main() {

  std::list<AorB> list{A(), B(), A(), A(), B()};

  for (auto& each : list) std::visit(foo, each);      // ERROR!
  for (auto& each : list) std::visit(foo_obj, each);  // OK!

  return 0;
}
2

There are 2 best solutions below

2
On BEST ANSWER

You might use lambda to handle overloads:

for (auto& each : list) std::visit([](auto e){ return foo(e);}, each);

Demo

3
On

Think about what you're doing here: You call visit and pass it "something that can be called".

That's just one something, not "whatever the compiler can find named foo"

To implement what you're asking for, the compiler would have to automatically build some kind of thing containing all the overloads of foo, and then pass it to visit - and that's what you are doing with the foo_obj