Timtro
Timtro

Reputation: 428

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

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;
}

Upvotes: 3

Views: 2302

Answers (2)

Jarod42
Jarod42

Reputation: 217810

You might use lambda to handle overloads:

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

Demo

Upvotes: 6

Marshall Clow
Marshall Clow

Reputation: 16680

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

Upvotes: 2

Related Questions