views:

54

answers:

4

Generally, I would use boost::mpl::for_each<>() to traverse a boost::mpl::vector, but this requires a functor with a template function declared like the following:

template<typename T> void operator()(T&){T::staticCall();}

My problem with this is that I don't want the object T to be instantiated by for_each<>. I don't need the T parameter in the operator() at all. Is there a way to accomplish this, or an alternative to for_each<> that doesn't pass an object of type T to the template function?

Optimally, I would like the operator() definition to look like this:

template<typename T> void operator()(){T::staticCall();}

And of course, I don't want T to be instantiated at all prior to the call. Any other tips/suggestions are also welcome.

A: 

Well, first of all, the static call in your code means that your object will exist. Before/after is meaningless in that regard. The only time, "I don't want T to be instantiated at all prior to the call," make sense is when T is a template. It's not, because it can't be. It is true that it is that line that causes the object to exist, but I am pretty sure it won't just exist there once the product is compiled.

Second of all, I don't believe that there's a current method to use for_each without instantiating. IMHO this is a bug in MPL caused by a questionable decision to use operator(). Won't say it's wrong since I know the developer and he's a lot smarter than I am, but it seems so from here now that you bring this up.

So, I think you're stuck having to remake a for_each that calls a templated function that doesn't require the parameter. I'm almost certain it is possible, but also equally certain it's not readily available as a premade component in MPL.

Noah Roberts
+2  A: 

Interesting question! As far as I can tell, Boost.MPL does not seem to provide such an algorithm. However, writing your own should not be too difficult using iterators.

Here is a possible solution:

#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/vector.hpp>

using namespace boost::mpl;


namespace detail {

template < typename Begin, typename End, typename F >
struct static_for_each
{
    static void call( )
    {
        typedef typename Begin::type currentType;

        F::template call< currentType >();
        static_for_each< typename next< Begin >::type, End, F >::call();
    }
};


template < typename End, typename F >
struct static_for_each< End, End, F >
{
    static void call( )
    {
    }
};

} // namespace detail


template < typename Sequence, typename F >
void static_for_each( )
{
    typedef typename begin< Sequence >::type begin;
    typedef typename end< Sequence >::type   end;

    detail::static_for_each< begin, end, F >::call();
}

[The naming may not be very well chosen, but well...]

Here is how you would use this algorithm:

struct Foo
{
    static void staticMemberFunction( )
    {
        std::cout << "Foo";
    }
};


struct Bar
{
    static void staticMemberFunction( )
    {
        std::cout << "Bar";
    }
};


struct CallStaticMemberFunction
{
    template < typename T >
    static void call()
    {
        T::staticMemberFunction();
    }
};


int main()
{
    typedef vector< Foo, Bar > sequence;

    static_for_each< sequence, CallStatic >(); // prints "FooBar"
}
Luc Touraille
A: 

Marcin, you're very right. I've been thinking this along and I don't see an easy solution for this. Even if you cannot write the empty operator(), it would be at least possible to use a pointer, that doesn't need an actual object to exist. You have to roll your own implementation, it seems.

Diego Sevilla