3

I would like to call a function on all elements of a boost::fusion::vector. The elements are of types like this:

class A {
    ...
    void print_with_prefix(const char *prefix) {
        std::cout << prefix << *this;
    }
};

One can call this function on each element in this way:

// Call print_with_prefix() on a boost::fusion sequence:

struct CallPrintWithPrefix {
    const char *prefix_;
    CallPrintWithPrefix(const char *prefix) : prefix_(prefix) {}
    template <class T> void operator()(T &element) const {
        element.print_with_prefix(prefix);
    }
}

template <class BoostFusionVector>
void print_all(BoostFusionVector &v, const char *prefix) {
    boost::fusion::for_each(v, CallPrintWithPrefix(prefix));
}

However, this implementation of print_all() including helper class is pretty ugly and seems overly complicated! Assuming C++0x is allowed, what is the right way to implement it?

hrr
  • 1,807
  • 2
  • 21
  • 35

1 Answers1

3

What you did is the right way. C++0x can't help much in that respect because e.g. lambda expressions are not polymorphic, so at the end of the day you'll have to write a template somewhere (which unfortunately must be at namespace scope, even with C++0x), like you did with the operator().

Some libraries like Boost.Phoenix allow to create polymorphic functors on the fly though. For instance ref(std::cout) << arg1 creates an object that is capable of passing any kind of argument to std::cout. It won't help in your case since you're calling a member function.

It's the second time I'm mentioning it today, but I do have a make_overload facility that allows me to create an overloaded functor on the fly. It could help in your case if the set of element types is small and not likely to change. For instance assuming there's only two such types A and B:

auto overload = make_overload(
    [prefix](A& a)
    { a.print_with_prefix(prefix); }
    , [prefix](B& c)
    { b.print_with_prefix(prefix); } );
boost::fusion::for_each(v, overload);
Luc Danton
  • 34,649
  • 6
  • 70
  • 114
  • Thanks for your explanation! Your make_overload magic seems pretty powerful! (Do you have a link for it?) In my particular case there are about 10 different types, so this would be lengthy, too. – hrr Jul 29 '11 at 13:18
  • 1
    @hrr No, I don't have my make_overload publicly available (I suppose I should). Given that it only has one (small) dependency on the rest of my code, I extracted it and you can see it [here](http://ideone.com/YeGXP). If you have any question regarding it you can drop in chat (I'm usually in room Lounge) and leave me a message even if I'm not here. This is preferred to filling up the comment space. – Luc Danton Jul 29 '11 at 13:54
  • The code looks pretty polished, thank you for posting it! Admittedly, I don't know all the fine C++0x constructs yet, is there a good referen... never mind, I should probably ask this in Lounge. – hrr Jul 29 '11 at 18:37