Search code examples
c++boostvectorforeachboost-mpl

Is it possible to iterate an mpl::vector at run time without instantiating the types in the vector?


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.


Solution

  • 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, CallStaticMemberFunction >(); // prints "FooBar"
    }