Tree traversal using std :: for_each

I am new to using algorithmand functionalin C ++. I need to do a tree traversal and execute a function for each element. See code below.

It works, but I have a few things that I don't like, and maybe they can do better. Please note that I am limited to the rather old version of g ++ (4.4.7) and cannot use lambda functions.

  • I use a wrapper function do_walkand std::bindto call a member function walkfor each element. Is there a way to avoid a wrapper function and directly call a member function?

  • I am using typedef for a callback function UnaryFunction. I would rather use the template version walk. However, when I change the code to use the template, I get the following compilation error: error: no matching function for call to 'bind(<unresolved overloaded function type>, std::_Placeholder<1>&, void (*&)(const Elem&))'. Can templates be used in this context?

  • Perhaps there is an alternative std::for_eachthat is better suited for this kind of tree traversal?

My code is:

#include <list>
#include <algorithm>
#include <functional>

struct Elem;
typedef void (*UnaryFunction)(const Elem&); // (2)

struct Elem
{
    std::list<Elem> children; // Some container, std::list for now.

    //template< class UnaryFunction > // (2)
    void walk(UnaryFunction f) const
    {
        // Walk all children.
        std::for_each(
            children.begin(),
            children.end(),
            std::bind(do_walk, std::placeholders::_1, f)); // (1)

        // Walk this object.
        f(*this);
    }

    //template< class UnaryFunction > // (2)
    static void do_walk(const Elem& elem, UnaryFunction f) // (1)
    {
        elem.walk(f);
    }
};

void pretty_print(const Elem& elem)
{
    // Pretty print element.
}

int main()
{
    Elem root;
    // Create tree somehow.
    root.walk(pretty_print);
    return 0;
}
+4
source share
2 answers
  • std::bindable to call member functions (passing the first argument to an implicit parameter this), so you can replace it do_walklike this:

    std::bind(&Elem::walk, std::placeholders::_1, f)
    
  • walk , bind ing , . , :

    std::bind(&Elem::walk<UnaryFunction>, std::placeholders::_1, f)
    
  • , std::for_each .

[ ] gcc 4.4.7

+6

std:: function, . sumarryze:

- do_walk std:: bind . -?

. std:: function

typedef UnaryFunction. . , : : 'bind (, std:: _ Placeholder < 1 > &, void (* &) (const Elem &))'. ?

. std:: function + variadic

, std:: for_each, ?

, std:: for_each

#include <list>
#include <algorithm>
#include <functional>


struct Elem
{
   std::list<Elem> children; // Some container, std::list for now.

                          //template< class UnaryFunction > // (2)
   template<typename ...TArgs>
   void walk( std::function<TArgs...> f ) const
   {
       // Walk all children.
       std::for_each(
           children.begin(),
           children.end(),
           f ); // (1) NO WRAPPER
   }
};

void pretty_print( const Elem& elem )
{
    // Pretty print element.
}

int main()
{
   Elem root;
   Elem root1;
   root.children.push_back( root1 );

   // Create tree somehow.
   root.walk<void( const Elem& )>( pretty_print );
   // or root.walk<decltype( pretty_print )>( pretty_print ); if you do not 
   // want to clarify type
   return 0;
}
+1

Source: https://habr.com/ru/post/1690013/


All Articles