Reputation: 15
It seems like it is not straightforward to call std::visit
within a lambda using a visitor that is a function object captured by value. Capturing by reference works fine though. Why is this the case and is it somehow possible to do this?
I do not understand the compile error message in this case, from MSVC 2017:
std::visit': no matching overloaded function found
Failed to specialize function template unknown-type std::visit(_Callable &&,_Variants &&...)
I assumed that the template argument deduction would behave very similar to just calling std::visit
without the lambda that wraps the call.
Code illustrating the issue:
#include <variant>
struct T {
void operator()(int i) {};
void operator()(float f) {};
};
int main()
{
std::variant<int, float> v = 1;
T t;
// Does not compile.
//auto l1 = [t](auto v) { std::visit(t, v); };
//l1(v);
// Compiles.
auto l2 = [&t](auto v) { std::visit(t, v); };
l2(v);
// Compiles.
std::visit(t, v);
}
Upvotes: 1
Views: 1216
Reputation: 519
The call operator generated by the lambda is marked const, so as with a const method all of the members of this are marked const as well. Since the call operators of T are not marked as const, you can't call them from the lambda. It works for the lambda that captures by reference because const does not propagate with pointer and reference data members.
So to resolve it, you can mark the lambda mutable which will make the call operator not const, capture by reference as you do, or mark the call operators of T const.
Upvotes: 5