使用std :: for_each进行树遍历

rve*_*erd 4 c++ templates stl

我是相当新的使用algorithmfunctionalC++中.我需要进行树遍历并为每个元素执行一个函数.请参阅下面的代码.

这有效,但我有一些我不喜欢的事情,或许可以做得更好.请注意,我仅限于相当旧版本的g ++(4.4.7),并且不能使用lambda函数.

  1. 我使用包装函数do_walk并在每个元素上std::bind调用成员函数walk.有没有办法避免包装函数并直接调用成员函数?

  2. 我使用typedef作为回调函数UnaryFunction.我更喜欢使用模板版本walk.但是,当我更改代码以使用模板时,我得到以下编译错误:error: no matching function for call to 'bind(<unresolved overloaded function type>, std::_Placeholder<1>&, void (*&)(const Elem&))'.是否可以在此上下文中使用模板?

  3. 也许有一种替代方案std::for_each更适合这种树遍历?

我的代码到目前为止:

#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;
}
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 6

  1. std::bind能够调用成员函数(将第一个参数传递给隐式this参数),因此您可以替换do_walk为:

    std::bind(&Elem::walk, std::placeholders::_1, f)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 制作walk模板的问题在于,在进行时,bind不清楚应该使用哪个实例化.您可以通过显式指定模板参数来消除歧义:

    std::bind(&Elem::walk<UnaryFunction>, std::placeholders::_1, f)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我相信std::for_each很好.

[实例]使用gcc 4.4.7