I'm trying to experiment with making a visitor with just a simple class, with overloads of operator() for each type in the variant.
I expected this to work (as it's how I assumed it worked for lamdba functions):
#include <variant>
#include <iostream>
using Example = std::variant<int, float, bool>;
class ExampleVisitor {
void operator()(int& i) {
std::cout << "Integer: " << i << '\n';
}
void operator()(float& f) {
std::cout << "Float: " << f << '\n';
}
void operator()(bool& b) {
std::cout << "Boolean: " << b << '\n';
}
};
int main() {
Example example = 1234;
ExampleVisitor visitor;
std::visit(visitor, example);
}
However compiling this code (on gcc version 9.3.0) results in a rather cryptic error error: no type named ‘type’
, which I can't really understand. I think it has something to do with std::visit
deducing the return type of the visitor, but I'm not too sure on the fix.
Full error:
In file included from visit.cpp:1:
/usr/include/c++/9/variant: In instantiation of ‘constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with bool __use_index = false; bool __same_return_types = true; _Visitor = ExampleVisitor&; _Variants = {std::variant<int, float, bool>&}]’:
/usr/include/c++/9/variant:1654:24: required from ‘constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = ExampleVisitor&; _Variants = {std::variant<int, float, bool>&}]’
visit.cpp:23:30: required from here
/usr/include/c++/9/variant:1634:13: error: no type named ‘type’ in ‘std::conditional_t<false, std::__detail::__variant::__variant_idx_cookie, std::invoke_result<ExampleVisitor&, int&> >’ {aka ‘struct std::invoke_result<ExampleVisitor&, int&>’}
1634 | using _Result_type = typename std::conditional_t<__use_index,
| ^~~~~~~~~~~~
/usr/include/c++/9/variant:1638:23: error: no type named ‘type’ in ‘std::conditional<false, std::__detail::__variant::__variant_idx_cookie, std::invoke_result<ExampleVisitor&, int&> >::type’ {aka ‘struct std::invoke_result<ExampleVisitor&, int&>’}
1638 | constexpr auto& __vtable = __detail::__variant::__gen_vtable<
|
Yes, it's certainly possible. The issue is, your overload set inside ExampleVisitor
is private
, so std::visit
doesn't find an appropriate operator()
to use (as far as it can tell, no operator()
s exist at all).
You can fix this by just making the overload set public
:
class ExampleVisitor {
public:
// ... all overloads
};
Or by making the class
into a struct
which changes the default access specifier.
Here's a demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With