I have the code below and why visitor1
and visitor2
gives errors?
Does that mean the visitor cannot return one type within the variant?
#include <iostream>
#include <variant>
struct Visitor1
{
template <class T>
T operator()(const T & t) const
{
return (t);
}
};
struct Visitor2
{
int operator()(const int & t) const
{
return std::get<int>(t);
}
char operator()(const char & t) const
{
return std::get<char>(t);
}
};
struct Visitor3
{
void operator()(const int & t) const
{
std::cout<<t;
}
void operator()(const char & t) const
{
std::cout<<t;
}
};
int main()
{
std::variant<int, char> v{char(100)};
std::visit(Visitor3{}, v);
auto t = std::visit(Visitor2{}, v); //fails
//auto t = std::visit(Visitor1{}, v); //fails
std::cout << t;
}
I know I can use std::get()
, but the issue is I can only use auto
with std::get()
, if I do something like below, the x
is not accessible outside of the if/else scope:
bool b;
Variant v;
if (b)
{
auto x = std::get<int>(v);
}
else
{
auto x = std::get<char>(v);
}
// I want to do something with x here out of if/else
I have the code below and why visitor1 and visitor2 gives errors?
Because C++ is a strongly typed language.
When you write
auto t = std::visit(Visitor2{}, v); //fails
the compiler must decide compile-time which type is t
, so must decide which type return std::visit(Visitor2{}, v)
.
If Visitor2
return a char
, when v
contains a char
, or a int
, when v
contain a int
, the compiler can't choose (compile-time!) the type returned from std::visit()
[there is also the problem (Visitor2
only) that t
, inside operator()
's, is a int
or a char
, so you can't apply std::get()
to it].
Same problem with Visitor1
: the template operator()
return the template type so int
or char
for a std::variant<int, char>
.
Visitor3
works because both operator()
return void
, so the compiler can resolve (compile-time) that std::visit(Visitor3{}, v)
return (in a sense) void
.
Maybe is better explained in this page:
[
std::visit()
] Effectively returnsstd::invoke(std::forward<Visitor>(vis), std::get<is>(std::forward<Variants>(vars))...)
, where
is...
isvars.index()...
. The return type is deduced from the returned expression as if bydecltype
.The call is ill-formed if the invocation above is not a valid expression of the same type and value category, for all combinations of alternative types of all variants.