Would a template work for std::variant's visit?

和自甴很熟 提交于 2021-01-27 20:06:40

问题


Earlier I asked this question about std::variant. Considering that the types hold by the variant are all printable by std::cout, is there a simple way to implement a visitor?

Here for example, all the way down you have several lambdas to cover each type, but all do the same thing (except std::string): std::cout << arg << ' ';. Is there a way to not repeat my self?

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

and write instead:

   std::visit(  [](auto arg) { std::cout << arg; }, v);

or something like:

template<typename T>
void printer(T arg) {std::cout << arg; }
//.......
std::visit(printer, v);

回答1:


No need to copy

std::visit(  [](auto&& arg) { std::cout << arg; }, v);

this takes arg by (forwarding) reference. I don't bother forwarding it; I don't care if it is an rvalue or lvalue really.

The template function doesn't work, because visit requires an object, and template functions aren't objects of functions; you cannot (yet) pass overload set names as objects in C++.

The overload trick is mainly when you want to dispatch different behavior.

One thing you can do is

template<typename T>
void printer(T arg) {std::cout << arg; }

std::visit([](auto&&arg){printer(arg);}, v);

or

#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)...); }

then we get:

template<typename T>
void printer(T arg) {std::cout << arg; }

std::visit(OVERLOADS_OF(printer), v);

which creates an anonymous object that represents the overload set of functions named by the token printer.



来源:https://stackoverflow.com/questions/44058784/would-a-template-work-for-stdvariants-visit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!