私は次のmplシーケンスを持っています
boost::mpl::vector_c<std::size_t, 0, 1, 2, 0, 1, 0>
そして私はそれを次のアルゴリズム(実行時バージョン)に従って変換する必要があります:
i=0
output_sequence=[]
for k in (0,...,len(input_sequence)-1):
if input_sequence[k] == 0:
output_sequence.append(i)
i=i+1
else:
output_sequence.append(-1)
私の場合の結果は次のようになります。
boost::mpl::vector_c<std::size_t, 0, -1, -1, 1, -1, 2>
std::transformまたはstd::accumulateを使用して実行時にこれを達成するための少なくとも2つの方法を想像できますが、mplを使用してコンパイル時に同じ結果を達成する方法の手がかりはありません。私にとっての主な問題は、出力シーケンスだけでなく、状態「i」(見つかった現在のゼロの数)を何らかの形で保存することです。
どうもありがとうございます!
追加した
HighCommander4の回答に基づいて採用された方法を皆さんと共有したいと思います。実際、boost::mpl::fold
カスタムメタ関数で使用することは可能です。HighCommander4と比較した場合の唯一の概念上の変更は、増大する出力シーケンスの最初の要素として現在使用可能な空きインデックスをパックすることです。を使用して、型計算の最後に削除できますboost::mpl::pop_font
。
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/print.hpp>
namespace mpl=boost::mpl;
struct assign_index
{
enum { dim_dynamic, dim_static };
template<typename Output, typename Index,
typename Enable = typename mpl::if_<
mpl::equal_to<Index, mpl::size_t<1> >,
mpl::size_t<dim_dynamic>,
mpl::size_t<dim_static> >::type>
struct apply
{
typedef typename mpl::push_back<Output, mpl::size_t<-1> >::type type;
};
template<typename Output, typename Index>
struct apply <Output, Index, mpl::size_t<dim_dynamic> >
{
typedef typename mpl::front<Output>::type current;
typedef typename mpl::next<current>::type next;
typedef typename mpl::push_back<Output, current>::type append_type;
typedef typename mpl::push_front<
typename mpl::pop_front<append_type>::type,next
>::type type;
};
};
template<class input_sequence>
struct map_indices
{
// The first element of state0 keeps track of the current index count.
typedef mpl::vector_c<std::size_t, 0> state0;
typedef typename mpl::fold<input_sequence, state0, assign_index>::type output_sequence;
// Remove the first element from the final output sequence
typedef typename mpl::pop_front<output_sequence>::type type;
};
int main (int argc, const char** argv)
{
typedef mpl::vector_c<std::size_t, 1, 2, 3, 1, 2, 1> input_sequence;
typedef map_indices<input_sequence>::type output_sequence;
int i;
i=mpl::print<mpl::at_c<output_sequence, 0>::type>();
i=mpl::print<mpl::at_c<output_sequence, 1>::type>();
i=mpl::print<mpl::at_c<output_sequence, 2>::type>();
i=mpl::print<mpl::at_c<output_sequence, 3>::type>();
i=mpl::print<mpl::at_c<output_sequence, 4>::type>();
i=mpl::print<mpl::at_c<output_sequence, 5>::type>();
return 0;
}
PS:この実装では、入力シーケンスの「1」は増加するインデックスに変換され、1より大きい値はstd :: size_t(-1)に変換されます。入力シーケンスでゼロを使用することはできません(他の場所でチェックされています)。
PS2:確認しましたが、実際にはboost::mpl
、任意のmpl
シーケンス(アルゴリズムの結果として取得されたシーケンスとして)をに戻す機能はありませんboost::mpl::vector
。したがって、これにもコードを書く必要があります...私はコードを適応させることになりました
<boost/fusion/container/vector/detail/as_vector.hpp>
タイプ計算結果を「正規化」します。
ありがとうございました!