早些时候我向question询问std::variant
。考虑到变体所持有的类型都可以由std::cout
打印,是否有一种简单的方法来实现访问者?
Here,你一直都有几个lambdas来覆盖每个类型,但所有都做同样的事情(std::string
除外):std::cout << arg << ' ';
。有没有办法不重复自我?
std::visit(overloaded {
[](int arg) { std::cout << arg; },
[](long arg) { std::cout << arg; },
[](double arg) { std::cout << arg; }
// I removed the std::string case
}, v); // v is the std::variant
然后写下来:
std::visit( [](auto arg) { std::cout << arg; }, v);
或类似的东西:
template<typename T>
void printer(T arg) {std::cout << arg; }
//.......
std::visit(printer, v);
答案 0 :(得分:2)
无需复制
std::visit( [](auto&& arg) { std::cout << arg; }, v);
这需要arg
个(转发)引用。我不打算转发它;我不在乎它是否真的是左值或左值。
模板功能不起作用,因为访问需要一个对象,而模板功能不是功能对象;你不能(还)将重载集名称作为C ++中的对象传递。
overload
技巧主要是在您想要分派不同的行为时。
你可以做的一件事是
template<typename T>
void printer(T arg) {std::cout << arg; }
std::visit([](auto&&arg){printer(arg);}, v);
或
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype( __VA_ARGS__ )
#define OVERLOADS_OF(...) \
[](auto&&...args) \
RETURNS( __VA_ARGS__(decltype(args)(args)...) ) \
{ return __VA_ARGS__(decltype(args)(args)...); }
然后我们得到:
template<typename T>
void printer(T arg) {std::cout << arg; }
std::visit(OVERLOADS_OF(printer), v);
创建一个匿名对象,该对象表示由令牌printer
命名的函数的重载集。