I have a boost::mpl::vector
with N
elements, say:
typedef boost::mpl::vector<int,float,double,short,char> my_vector;
I wish to obtain a sequence containing the first M
elements of my_vector
. So if M
is 2 I want out a:
typedef boost::mpl::vector<int,float> my_mvector;
Initially I thought of using erase<s,first,last>
but was unable to figure out suitable template parameters for first
and last
. (I was using at_c<...>::type
.) However, it is also my understanding that filter_view
can also be used for the task. What is the best way of going about this?
Erase is a reasonable solution for your problem.
mpl::begin<T>
which is advanced by the number of elements you are interested in returning.mpl::end<T>
The code below assumes that you want the metafunction to return the original type if the number of elements in the vector is less than the requested number. It's also possible to use a static assertion to verify that input integral type is less than or equal to the size of the vector.
I provied both a first_n_elements
which takes an MPL integral constant and first_n_elements_c
which simply takes an integer.
You could also use iterator_range<>
along with the begin and cut iterators in the below code, if you want to use a view. I'm not sure what the advantages are of one over the other in this case.
#include <boost/mpl/vector.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/erase.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/less.hpp>
namespace mpl = boost::mpl;
namespace detail
{
// Note, this is an internal detail. Please use the structures below
template <typename T, typename N>
struct erase_after_n
{
typedef typename mpl::begin<T>::type begin_iter;
typedef typename mpl::advance<begin_iter, N>::type cut_iter;
typedef typename mpl::end<T>::type end_iter;
typedef
typename mpl::erase< T,cut_iter, end_iter >::type type;
};
}
template <typename T, typename N>
struct first_n_elements
{
typedef
typename mpl::eval_if< mpl::less < mpl::size<T>, N >,
T,
detail::erase_after_n<T, N> >::type type;
};
template <typename T, int N>
struct first_n_elements_c
{
typedef
typename first_n_elements<T, mpl::int_<N> >::type type ;
};