I'm trying to pass values to a function accepting a std::variant
.
I noticed I can use a function accepting a const reference to a variant value, but not a reference alone. Consider this code
#include <variant>
#include <queue>
#include <iostream>
struct Foo{ std::string msg{"foo"}; };
struct Bar{ std::string msg{"bar"}; };
using FooBar = std::variant<Foo,Bar>;
void f1(const FooBar&)
{
std::cout << "yay" << std::endl;
}
void f2(FooBar&)
{
std::cout << "wow" << std::endl;
}
int main()
{
Foo f;
Bar b;
f1(f); // fine
f1(b); // fine
f2(f); // compile error
}
gives me error
invalid initialization of reference of type 'FooBar&' {aka 'std::variant<Foo, Bar>&'} from expression of type 'Foo'
42 | f2(f);
so the first question is: why is that prohibited? I can't figure out.
Why I'm doing this?
I'm trying to use two accessor function to read and modify the values using std::visit
, something like this:
#include <variant>
#include <queue>
#include <iostream>
struct Foo{ std::string msg{"foo"}; };
struct Bar{ std::string msg{"bar"}; };
using FooBar = std::variant<Foo,Bar>;
std::string f3(const FooBar& fb)
{
return std::visit([](auto& foobar){
std::string ret = "yay ";
return ret + foobar.msg;
}, fb);
}
void f4(FooBar& fb)
{
std::visit([](auto& foobar){
foobar.msg += "doo";
}, fb);
}
int main()
{
Foo f;
Bar b;
std:: cout << f3(f) << " " << f3(b); // fine
f4(f); // does not compile
}
which of course does not compile with
error: cannot bind non-const lvalue reference of type 'FooBar&' {aka 'std::variant<Foo, Bar>&'} to an rvalue of type 'FooBar' {aka 'std::variant<Foo, Bar>'}
44 | f4(f);
| ^
So second question: how can I achieve this behaviour?