簡単な質問は本当に、私はいくつかの背景を与えてみましょう:boost :: mpl for_eachから抜け出す方法はありますか?
私は、各タイプのIDを持っているタイプのmpl::vector
を持って、実行時に、私はこのベクトルを反復処理し、指定されたidの一致タイプを見つけるためにmpl::for_each
を使用。しかし、一度発見されれば、ループを続けることに意味がないので、質問は、そこから抜け出す方法があるかどうかです(例外を投げずに)?
簡単な質問は本当に、私はいくつかの背景を与えてみましょう:boost :: mpl for_eachから抜け出す方法はありますか?
私は、各タイプのIDを持っているタイプのmpl::vector
を持って、実行時に、私はこのベクトルを反復処理し、指定されたidの一致タイプを見つけるためにmpl::for_each
を使用。しかし、一度発見されれば、ループを続けることに意味がないので、質問は、そこから抜け出す方法があるかどうかです(例外を投げずに)?
find_if
のようなものを実装するために、私はbool
テンプレート引数を取るように(exec_if
それを呼び出す)for_eachを変更しました。 bool
は、実行が次のシーケンスで行われるべきか、または影響の早期復帰が早いかを示します。
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
namespace mpl = boost::mpl;
template< bool done = true >
struct exec_if_impl
{
template<typename Iterator, typename LastIterator, typename Pred, typename Exec>
static void execute(Iterator*, LastIterator*, Pred const&, Exec const&)
{
}
};
template<>
struct exec_if_impl<false>
{
template<typename Iterator, typename LastIterator, typename Pred, typename Exec>
static void execute(Iterator*, LastIterator*, Pred const& f, Exec const& e)
{
typedef typename mpl::deref<Iterator>::type item;
if (!f(static_cast<item*>(0)))
{
typedef typename mpl::next<Iterator>::type iter;
exec_if_impl<boost::is_same<iter, LastIterator>::value>
::execute(static_cast<iter*>(0), static_cast<LastIterator*>(0), f, e);
}
else
e(static_cast<item*>(0));
}
};
template<typename Sequence, typename Pred, typename Exec>
inline
void exec_if(Pred const& f, Exec const& e, Sequence* = 0)
{
BOOST_MPL_ASSERT((mpl::is_sequence<Sequence>));
typedef typename mpl::begin<Sequence>::type first;
typedef typename mpl::end<Sequence>::type last;
exec_if_impl<boost::is_same<first,last>::value>
::execute(static_cast<first*>(0), static_cast<last*>(0), f, e);
}
namespace msg
{
struct m1 { enum { TYPE = 1 }; static const char* name() { return "m1"; } };
struct m2 { enum { TYPE = 2 }; static const char* name() { return "m2"; } };
struct m3 { enum { TYPE = 3 }; static const char* name() { return "m3"; } };
struct m4 { enum { TYPE = 4 }; static const char* name() { return "m4"; } };
struct m5 { enum { TYPE = 5 }; static const char* name() { return "m5"; } };
}
struct checker
{
checker(int chk_type) : type(chk_type) {}
template <typename Mtype>
bool operator()(Mtype* = 0) const
{
return Mtype::TYPE == type;
}
int type;
};
struct exec
{
template <typename Mtype>
void operator()(Mtype* = 0) const
{
std::cout << Mtype::name() << " executed" << std::endl;
}
};
int main(void)
{
typedef mpl::vector<msg::m1, msg::m2, msg::m3, msg::m4, msg::m5> mseq;
checker chk(3);
exec_if<mseq>(chk, exec());
return 0;
}
私は今、述語が一致したときに、その後、ファンクタは実行するために型にトリガされます、exec_if
にこれを変更する - これは私が必要とするまさにありません。
いいえ、mpl::for_each
を「中断する」方法はありません。それは、私はあなたの問題を誤解しているかもしれない、と述べたが、あなたがmpl::for_each
よりmpl::find_if
より多くを必要と私には思われている:
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/vector.hpp>
template<int N>
struct Foo { enum { id = N }; };
template<int N>
struct has_nested_id {
template<class T>
struct apply {
static const bool value = (N == T::id);
};
};
int main()
{
typedef boost::mpl::find_if
<
boost::mpl::vector<Foo<1>, Foo<2>, Foo<3> >,
has_nested_id<3>::apply<boost::mpl::_1>
>::type iterator_type;
typedef boost::mpl::deref<iterator_type>::type type; // result is Foo<3>
}
私は 'find_if'が必要ですが、上記のメタではなくランタイムバージョンが必要です。私が持っている問題は、 '3'は実行時にしか利用できないということです。 – Nim
@ Nim-MPLは、コンパイル時に既知の値でしかテンプレートをインスタンス化できないため、コンパイル時の構造体でのみ機能します。ランタイムまでインデックスがわからない場合は、他の方法を使用する必要があります。 – templatetypedef
@templatetypedef、はい私は、現在のアプローチは 'for_each'のコードを見つけようとしていて、それをハックすることができるかどうかを調べるために、何らかの形で実行時が繰り返されるので、方法が必要です。 – Nim