これは、 Luc Touraille の answerから非常にインスピレーションを得た代替ソリューションです。
このバージョンは、関数の代わりにMetafunction クラスstatic_for_each
を使用して行われます。これにより、関数スコープの外でも呼び出すことができます (実行時に不要な関数が呼び出されないように、コンパイル時にジョブを完全に実行する必要がある場合に役立ちます)。
first
さらに、とtypedefのおかげでより多くの対話last
が可能になり、必要に応じてループから情報を取得できるようになりreturn
ます。
Previous
メタ関数クラスに渡される2 番目のテンプレート パラメーターのおかげで、各反復内で前の反復結果にアクセスすることもできますF
。
最後に、テンプレート パラメーターを使用してループ プロセスにデータを提供できます。これは、最初の反復Initial
のパラメーターの値として与えられます。Previous
# include <boost/mpl/begin_end.hpp>
# include <boost/mpl/next_prior.hpp>
# include <boost/mpl/apply.hpp>
namespace detail_static_for_each
{
// Loop
template<typename Begin, typename End, typename F, typename Previous>
struct static_for_each
{
private:
typedef typename Begin::type current_type;
public:
typedef typename boost::mpl::apply<F, current_type, Previous>::type first;
typedef typename static_for_each<typename boost::mpl::next<Begin>::type, End, F, first>::last last;
};
// End of loop
template<typename End, typename F, typename Last>
struct static_for_each<End, End, F, Last>
{
public:
typedef Last first;
typedef Last last;
};
} // namespace detail_static_for_each
// Public interface
template<typename Sequence, typename F, typename Initial = void>
struct static_for_each
{
private:
typedef typename boost::mpl::begin<Sequence>::type begin;
typedef typename boost::mpl::end<Sequence>::type end;
typedef typename detail_static_for_each::static_for_each<begin, end, F, Initial> loop;
public:
typedef typename loop::first first;
typedef typename loop::last last;
};
データの提供と取得の両方を行う簡単な例を次に示します。
# include <iostream>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/vector.hpp>
# include "static_for_each.hpp"
struct is_there_a_float
{
template<typename currentItem, typename PreviousIterationType>
struct apply
{
typedef typename boost::mpl::if_< PreviousIterationType,
PreviousIterationType,
boost::is_same<float, currentItem> >::type type;
};
};
struct test
{
typedef boost::mpl::vector< char, long, long, double, float, int, char > sequence;
typedef static_for_each<sequence, is_there_a_float, boost::false_type>::last found;
};
int main(void)
{
std::cout << std::boolalpha << test::found::value << std::endl;
return (0);
}
これらの機能により、static_for_each
一般的なランタイム ループ ( while
、for
、BOOST_FOREACH ...) をより直接的に操作できるようになるため、 の使用がより類似したものになります。