简体   繁体   中英

std::visit Vs For_each loop

Let the data structure be anything (Array, Vectors, Std::Variant). But what is the difference in traversing using just for/for_each against std::visit.

for (auto& Element: collection){
        std::visit([](auto arg){std::cout << arg << " ";}, Element);
    
}

And

for_each(collection.begin(), collection.end(), [](Element& e)
{
   std::cout << e;
});

Note1: I know C-style for loop vs C++ for_each..For_each avoids typo error/syntactic sugar. so we can be happy with just for_each.

Note2: I know visitor design pattern too, which will be used for polymorphic object against polymorphic behaviour.

But still I couldn't appreciate and understand std::visit .

And when I digged further, I came to know something called Overload pattern .

template<typename ... Ts>                                                
struct Overload : Ts ... { 
    using Ts::operator() ...;
};
template<class... Ts> Overload(Ts...) -> Overload<Ts...>;

But this Overload pattern too can be done using the same for_each right?

Thanks in advance for the reply.,

The difference between your first and second method is that the second does not work if your collection elements are variants. The example below compiles and lists your options.

Methods 2 and 4 are the only elegant ones I believe. But Method 2 is limited (see how it prints) while Method 4 gives you all the flexibility you may wish for.

But this does not necessarily mean Method 4 is the way to go. Place some intentional errors in Method 4 and then look at the error messages. They are mostly unintelligible.

#include <iostream>
#include <utility>
#include <variant>
#include <vector>
#include <algorithm>

using Element = std::variant<int, std::string>;
using Collection = std::vector<Element>;
Collection c = {1, 2, "three", "four", 5};

auto print_int = [](int const & e)
{
    std::cout << "int: " << e << std::endl;
};

auto print_str = [](std::string const & e)
{
    std::cout << "string: " << e << std::endl;
};

auto print_any = [](auto && e)
{
    std::cout << "element: " << e << std::endl;
};

void Method1 ()
{
    for (Element const & e: c)
    {
        {
            auto const * i = std::get_if<int>(&e);
            if (i)
            {
                print_int(*i);
                continue;
            }
        }
        {
            auto const * s = std::get_if<std::string>(&e);
            if (s)
            {
                print_str(*s);
                continue;
            }
        }
    }
}

void Method2 ()
{
    for (Element const & e: c)
    {
        std::visit(print_any, e);
    }
}

void Method3 ()
{
    std::for_each(c.cbegin(), c.cend(), [](Element const & e)
    {
       std::visit(print_any, e);
    });
}

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
void Method4 ()
{
    for (Element const & e: c)
    {
        std::visit(overloaded
        {
            [](int i) { print_int(i); },
            [](std::string s) { print_str(s) ; }
        }, e);
    }
}

int main ()
{
    std::cout << std::endl << "Method1" << std::endl;
    Method1();
    std::cout << std::endl << "Method2" << std::endl;
    Method2();
    std::cout << std::endl << "Method3" << std::endl;
    Method3();
    std::cout << std::endl << "Method4" << std::endl;
    Method4();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM