Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 875
Marcin Avatar asked Oct 29 '10 15:10

Marcin


People also ask

How to iterate through vector without using iterators in STL?

The iterator is not the only way to iterate through any STL container. There exists a better and efficient way to iterate through vector without using iterators. It can be iterated using the values stored in any container. Below is the syntax for the same for vectors:

How to iterate over a vector in C++?

The most classic C++ way to iterate over elements is using iterators. Remember that using vector::begin () and vector::end () allow accessing at pointers to the start and end of a vector respectively. Moreover, you can use vector::rbegin () and vector:rend () to get the reverse iterator pointing the last and the first element respectively.

How to update values in a vector without using iterators?

Updating values in vector: For updating values in a vector without using iterators traverse the values stored in vector using reference and updated the value. Below is the syntax for the same: Explanation: Here itr is an address to the value stored in vector which is used to traverse vectors.

How to iterate over a vector filled with random numbers?

Now, with a vector filled with random number, the subsequent step is checked which elements are stored on it. Using an index is a most used/classic way to iterate over the vector in C++, which is used in normal loops. With this approach it is possible to know the index position of the elements.


2 Answers

Just encountered the same situation and provided different solution to the problem which I would like to share. It's not as that obvious, but it uses an existing algorithm. The idea is to use pointers instead.

typedef boost::mpl::vector<type1*, type2*> container;

struct functor
{
    template<typename T> void operator()(T*)
    {
        std::cout << "created " << typeid(T).name() << std::endl;
    }
};

int main()
{
    boost::mpl::for_each<container>(functor());
}

so here we get a null pointers, but we don't care as we are not going to use them.

As I stated before that is not obvious in the code and would probably require some additional comments, but it still solves the question without writing any additional code.

added

I think Diego Sevilla suggested something similar.

like image 158
confucius Avatar answered Oct 18 '22 04:10

confucius


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"
}
like image 29
Luc Touraille Avatar answered Oct 18 '22 03:10

Luc Touraille