是否可以在没有 lambda 的情况下使用 std::visit(只是一个简单的 class)?
Is it possible to use std::visit without lambdas (just a simple class)?
我正在尝试使用简单的 class 来创建访问者,并为变体中的每种类型重载 operator()。
我希望它能起作用(因为我认为它对 lamdba 函数起作用):
#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);
}
但是编译此代码(在 gcc 版本 9.3.0 上)会导致一个相当神秘的错误 error: no type named ‘type’
,我无法真正理解。我认为这与 std::visit
推断访问者的 return 类型有关,但我不太确定修复方法。
完整错误:
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<
|
是的,这当然有可能。问题是,您在 ExampleVisitor
中设置的重载是 private
,因此 std::visit
找不到合适的 operator()
来使用(据它所知,没有 operator()
s 存在)。
您可以通过设置重载来解决这个问题 public
:
class ExampleVisitor {
public:
// ... all overloads
};
或者通过将 class
变成 struct
来更改默认访问说明符。
这是 demo.
我正在尝试使用简单的 class 来创建访问者,并为变体中的每种类型重载 operator()。
我希望它能起作用(因为我认为它对 lamdba 函数起作用):
#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);
}
但是编译此代码(在 gcc 版本 9.3.0 上)会导致一个相当神秘的错误 error: no type named ‘type’
,我无法真正理解。我认为这与 std::visit
推断访问者的 return 类型有关,但我不太确定修复方法。
完整错误:
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<
|
是的,这当然有可能。问题是,您在 ExampleVisitor
中设置的重载是 private
,因此 std::visit
找不到合适的 operator()
来使用(据它所知,没有 operator()
s 存在)。
您可以通过设置重载来解决这个问题 public
:
class ExampleVisitor {
public:
// ... all overloads
};
或者通过将 class
变成 struct
来更改默认访问说明符。
这是 demo.