Boost logo

Boost :

Subject: [boost] [Boost.Variant] Parameterized Visitors
From: Andy Jost (Andrew.Jost_at_[hidden])
Date: 2012-01-12 19:30:55


New poster.

When I'm using Boost.Variant, I often want to pass additional parameters to a visitor. A common case is when the variant is a class member and I want to have access to other members (or even "this") in the visitor.

I muddled through for a long time writing visitors with explicit constructors and data members to take whichever parameters I needed, but I finally got around to making this generic with Boost.Fusion and I love it. I'm wondering whether I should submit this for consideration as an addition to the Boost.Variant library and how.

First a few questions:

1. Is there already an equivalent solution that I should be aware of?

2. Should this be considered for an addition to Boost?

3. If so, how do I begin the review process?

4. This is a small change (400 or so lines of code). Is there anyone willing to help with the logistics, testing, and/or documentation (perhaps in exchange for a credit in the docs)?

Here's an example, which should be fairly self-explanatory:

struct A {}; struct B {}; struct C {};

struct my_visitor1 : param_visitor<my_visitor1, bool>
{
  result_type operator()(int, float, char, A) const {...}
  result_type operator()(int, float, char, B) const {...}
  result_type operator()(int, float, char, C) const {...}
};

struct my_visitor2 : fused_param_visitor<my_visitor2, bool>
{
  template<typename Sequence>
    result_type operator()(Sequence const &, A) const {...}
  ...
};

int main()
{
  boost::variant<A,B,C> abc;
  boost::apply_visitor(my_visitor1().tie(1, 3.14, 'k'), abc);
  boost::apply_visitor(my_visitor2().tie(1, 3.14, 'k'), abc);
  return 0;
}

In terms of technical detail, there's not much to it. The base classes provide tie() and load() methods to take arguments by reference or value, respectively. A call to one of those returns a helper object that contains a copy of the derived visitor and a fusion::vector of arguments. Visiting that causes the user-defined visitor to be called with all of the arguments. For parameter forwarding, I use an implementation of perfect forwarding based on boost/flyweight/detail/dyn_perfect_fwd.hpp (I used a default limit of 4 parameters).

Thanks,
Andy


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk