I'm trying to use std::bind
together with std::visit
in order to get a function where the visitor is bound.
I'm getting a "no instance of overloaded function" but I have no idea what I'm doing wrong with regards to bind.
How do I utilize std::bind
to capture the visitor?
#include <variant>
#include <functional>
#include <iostream>
using Somenum = std::variant<uint64_t, double>;
struct Visitor {
uint64_t operator()(const uint64_t& num) const {
return num;
}
uint64_t operator()(const double& num) const{
return 5;
}
};
int main(int argc, char **argv) {
const Somenum a = 3.0;
const Somenum b = (uint64_t)6;
const Visitor v{};
const auto f = std::bind(std::visit<Visitor, Somenum>, v, std::placeholders::_1);
const auto f2 = [&v](Somenum x) {
return std::visit(v, x);
};
std::cout << f(a) << std::endl << f(b)<< std::endl;
std::cout << f2(a) << std::endl << f2(b) << std::endl;
return 0;
}
Effectively I'd like f
and f2
to have the same behavior
Removing the line where f
is called allows everything to compile.
I can't explain the <unresolved overloaded function type>
error - but what you're doing is incorrect anyway. std::visit
takes a bunch of forwarding references, so std::visit<Visitor, Somenum>
is a function pointer whose type is something like:
decltype(auto)(*)(Visitor&&, Somenum&&);
Those are rvalue references. But you're not actually invoking this function with rvalues, you're invoking it with lvalues. const lvalues even. So the version you want is really std::visit<Visitor const&, Somenum const&>
. This works:
auto p = std::visit<Visitor const&, Somenum const&>;
const auto f = std::bind(p, v, std::placeholders::_1);
Again I'm not sure why you need to pre-declare p
.
This should hopefully make it clear why using the lambda is strongly preferred. You don't have to manually before template argument deduction just to get it right!