2013-11-22 11 views
9

は、私はここ遷移表としてstd::tr1::tupleを使用する一般的なステートマシンの独自の実装を持っている:実行時にboost :: fusion :: vectorの要素を見つける方法は?

template<State StartState, Event TriggerEvent, State TargetState> 
struct transition {...}; 

typedef std::tr1::tuple< transition< ready  , run  , running  > 
         , transition< running , terminate, terminating > 
         , transition< terminating, finish , terminated > 
         > transition_table; 

機能

template<typename Transitions> 
State find_next_state(State current 
        , Event event 
        , const Transitions& transition_table); 

与えられた遷移表の次の状態を見つけるためにあります現在の状態とイベントが表示されます。

これは、このプラットフォームのtuple実装が10個以上の項目をサポートしていないことを除いて、すべて正常に動作します。同じことがboost::tupleについても当てはまると思われますので、代わりにboost::fusion::vectorを採用しようとしています。しかし、それはfusion's find_ifが "unary MPL Lambda Expression"しか取らないように思えます。コンパイル時にのみ動作します。

上記のとおり、find_next_state()はどのように実装できますか?

注:

これだけGCC 4.1.2を提供するので、我々は、C++ 03 + TR1で立ち往生している独自の組み込みプラットフォーム。

+0

代替作業として、タプルをタプルにパックできますか? – Angew

+1

あなた自身の 'find_if'を書くのはどうですか?これは、実行時にフュージョンシーケンスと関数で動作しますか? – ForEveR

+0

最初に 'tuple'を使うのはなぜですか? 「移行」には何らかの状態がありますか?そうでなければ、 'mpl :: vector'と' mpl :: for_each'を使って実行時に反復処理することができます。 – Abyx

答えて

10

「」を書くことは、「見つかった値を返す」部分を除いて、ややこしいことです。 boost::fusion::vectorは異種コンテナなので、返す単一の権利タイプはありません。頭に浮かぶ一つの可能​​な解決策が見つかりました値で呼び出される継続関数受け入れている:intlongパラメータだけでなく、0引数はときだけの曖昧さ回避のためのものである

#include <boost/fusion/include/size.hpp> 
#include <boost/fusion/include/at_c.hpp> 

// private implementation details 
namespace detail{ 
// shorthand ... 
template<class S> 
struct fusion_size{ 
    static const unsigned value = 
    boost::fusion::result_of::size<S>::type::value; 
}; 

// classic compile-time counter 
template<unsigned> struct uint_{}; 

template<class Seq, class Pred, class F> 
void find_if(Seq&, Pred const&, F, uint_<fusion_size<Seq>::value>, int) 
{ /* reached the end, do nothing */ } 

template<class Seq, class Pred, class F, unsigned I> 
void find_if(Seq& s, Pred const& pred, F f, uint_<I>, long){ 
    if(pred(boost::fusion::at_c<I>(s))) 
    { 
     f(boost::fusion::at_c<I>(s)); 
     return; // bail as soon as we find it 
    } 
    find_if(s, pred, f, uint_<I+1>(), 0); 
} 
} // detail:: 

template<class Seq, class Pred, class F> 
void find_if(Seq& s, Pred const& pred, F f){ 
    detail::find_if(s, pred, f, detail::uint_<0>(), 0); 
} 

Live example.

I+1 == fusion_size<Seq>::value、両方の機能が同等に実行可能であるためです。 0がタイプintであると、最初のオーバーロード(最後のもの)が優先されます。

+0

それは私がそれを適応させることができると私が探しているものに十分に近いようです。私の実際の問題を見ておきたい戻り値を返してください。 ':)'私はいつも 'State'列挙型変数を返す必要があるので、これはケーキです。 (私は一致が見つからない場合は、スローする必要のあるバリアントと、あらかじめ定義された値を返す必要があるバリアントがありますが、ブール値パラメータを使用して処理することができ、さらにオーバーロードすることができます)。私はこのコードベースに入れたいとは思っていませんが、私が入札をするためにこれをマッサージした後、私はそれが必要かどうかを見ていきます。 – sbi

関連する問題