Я пишу шаблонную функцию, которая должна поменять местами два элемента boost::mpl::vector
(аналогично std::swap
). Сложность в том, что нет понятия переменной во время компиляции. Я написал черновик, но мне интересно, есть ли лучшие способы подойти к этому.
Мой текущий эскиз кода извлекает интегральный индекс из итераторов и выполняет копирование типа последовательности с заменой элементов. Вопрос - можно ли это сделать лучше:
#include <boost/mpl/distance.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/comparison.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/clear.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/or.hpp>
using boost::mpl::distance;
using boost::mpl::begin;
using boost::mpl::end;
using boost::mpl::next;
using boost::mpl::at;
using boost::mpl::or_;
using boost::mpl::int_;
using boost::mpl::eval_if;
using boost::mpl::greater;
using boost::mpl::equal;
using boost::mpl::clear;
using boost::mpl::push_back;
namespace boost { namespace mpl {
template<template<typename, typename> class T, class A, class B>
struct eval2 {
typedef typename T<typename A::type, typename B::type>::type type;
};
namespace details {
template <typename Dest_seq, typename It_end, typename It_first, typename It_second, typename It_idx>
struct copy_and_swap {
private:
typedef typename eval_if< is_same<It_idx, It_first>,
eval2<push_back, Dest_seq, deref<It_second> >,
eval_if<is_same<It_idx, It_second>,
eval2<push_back, Dest_seq, deref<It_first> >,
eval2<push_back, Dest_seq, deref<It_idx> >
>
>::type Limit_idx;
typedef typename next<It_idx>::type it_idx_next;
public:
// next step
typedef typename eval_if <is_same<it_idx_next, It_end>,
New_seq,
copy_and_swap<New_seq,
It_end,
It_first,
It_second,
it_idx_next>
>::type type;
};
} // namespace details
template<typename Seq, typename Begin, typename End>
struct swap {
private:
typedef typename begin<Seq>::type it_begin;
typedef typename end<Seq>::type it_end;
// get an empty container type "compatible" with Seq
typedef typename clear<Seq>::type Container_t;
// border case - swap self
typedef typename is_same<Begin, End>::type swap_self;
// border case - less than 2 elements in sequence
typedef typename less<size<Seq>, int_<2> >::type no_swap;
public:
// perform the element swapping
typedef typename eval_if <or_<swap_self, no_swap>,
Seq,
details::copy_and_swap<Container_t,
it_end,
Begin,
End,
it_begin >
>::type type;
};
} // namespace mpl
} // namespace boost
Эта метафункция может использоваться как:
struct value_printer {
template< typename U > void operator()(U x) {
std::cout << x << ',';
}
};
typedef vector_c<int, 1, 2, 3, 6, 5, 4>::type test_vect;
typedef begin<test_vect>::type it_beg;
typedef advance<it_beg, int_<2> >::type it;
typedef advance<it_beg, int_<5> >::type it_stop;
typedef m_swap<test_vect, it_stop, it>::type result;
boost::mpl::for_each< result >( value_printer() );
и результат 1,2,4,6,5,3,