开发者

What is the use of boost::visit_each?

I read the documentation on visit_each, but can't really see what exactly it does, as well as the general use for it, if ever开发者_StackOverflow社区y user has to overload it anyways. Someone care to enlighten me?


Edit: Maybe I'm just so confused because the following is the whole content of <boost/visit_each.hpp> and I just don't see any "magic" there to "visit each subobject":

namespace boost {
  template<typename Visitor, typename T>
  inline void visit_each(Visitor& visitor, const T& t, long)
  {
    visitor(t);
  }

  template<typename Visitor, typename T>
  inline void visit_each(Visitor& visitor, const T& t)
  {
    visit_each(visitor, t, 0);
  }
}

Maybe someone can give me a concrete example of how this is supposed to look like / work?


I guess this might be more helpful:

Design Overview - visit_each function template


I suspect the important part of that documentation is this line: "Library authors will be expected to add additional overloads that specialize the T argument for their classes, so that subobjects can be visited." In other words, there is no general use for it, it is just a common name for any visitor-based introspection mechanism. The way it is implemented, something will happen for all types, whether their writers were aware of its existance or not, so you don't get a compile-time failure.

It doesn't seem overly useful to me... practically speaking, it is just an internal function of the boost signals library, but I suppose if you're using that library anyhow specializing visit_each on your own types wouldn't hurt.

They mention finding signals::trackable objects. So presumably, they have provided a couple specializations for their own types within the signals library. Then they have a is_trackable functor. Or something similar.

struct trackable { };

struct Introspective {
    int a;
    double b;
    trackable c;
};

struct NotIntrospective {
    int a;
    double b;
    trackable c;
};

template<typename Visitor, typename T>
inline void visit_each(Visitor& visitor, const T& t, long) {
  visitor(t);    
} 

template<typename Visitor>
inline void visit_each(Visitor& visitor, const Introspective& t, int) {
  visitor(t); //"visits" the object as a whole

  //recursively visit the member objects; if unspecialized, will simply call `visitor(x)`
  visit_each(visitor, t.a, 0);
  visit_each(visitor, t.b, 0);
  visit_each(visitor, t.c, 0);
}

struct is_trackable {
  void operator()(const trackable&) { 
    //Do something
  }

  template<typename T>
  void operator()(const T&) { }
}

int main() {
    Introspective a;
    NotIntrospective b;
    trackable c;

    visit_each(is_trackable(), a, 0); //calls specialized version, finds `a.c`
    visit_each(is_trackable(), b, 0); //calls default version, finds nothing
    visit_each(is_trackable(), c, 0); //calls default version, which "visits" the 
                                      //object itself, and finds that it is trackable
}

The key thing is that visit_each itself doesn't do any magic, except provide a way for a call to visit_each to not fail to compile on an unrecognized type.


visit_each allows to inspect variables, bound by boost::bind. Canonical example is to inspect contents for this pointer and extract base boost::signals::trackable out of it.

class MyClass : boost::signals::trackable
{
    void my_method(int arg);
}

boost::signal<void()> signal;

signal.connect( boost::bind(&MyClass::my_method, this, 5) );

This way, the boost::signal will be able to accomplish safe callback subscription to the MyClass object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜