これは、テンプレートをツリーのようにインスタンス化し、現在訪問しているノードを追跡することによって実行できます。
namespace detail{
//This is used to store the visited nodes
template<int...> struct int_pack;
//Primary template
template<typename, int... I>
struct C;
//This is the leaf node
template<int... Is>
struct C<int_pack<Is...>> {
//The loop body goes here
static void f() {
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
//This is the recursive case
template <int I, int... Is, int... PIs>
struct C<int_pack<PIs...>, I,Is...> {
template <std::size_t... Idx>
static void f_help (std::index_sequence<Idx...>) {
//Store the current node in the pack
//and call `C::f` for each loop iteration
(void)std::initializer_list<int> {
(C<int_pack<PIs...,Idx>,Is...>::f(), 0)...
};
}
//Use tag dispatching to generate the loop iterations
static void f() {
f_help(std::make_index_sequence<I>{});
}
};
}
//Helper alias
template<int... Is>
using C = detail::C<detail::int_pack<>, Is...>;
使い方は非常に簡単です:
クランオン
C<2,3>::f();
この版画:あなたが注入できるように、これは、より汎用的にすることができ
static void detail::C<detail::int_pack<0, 0>>::f() [I = <>]
static void detail::C<detail::int_pack<0, 1>>::f() [I = <>]
static void detail::C<detail::int_pack<0, 2>>::f() [I = <>]
static void detail::C<detail::int_pack<1, 0>>::f() [I = <>]
static void detail::C<detail::int_pack<1, 1>>::f() [I = <>]
static void detail::C<detail::int_pack<1, 2>>::f() [I = <>]
Live Demo
ループ本体ラムダを介してクラスに追加しますが、これを一度しか行いたくなく、boost::hana
のような他の依存関係を取りたくない場合は、上記の解決策を実行する必要があります。ここではより一般的なバージョンの可能な実装は、(あなたは完璧な転送などでそれを改善することができる)です:
namespace detail{
template<int...> struct int_pack;
template<typename, int... I>
struct C;
template<int... Is>
struct C<int_pack<Is...>> {
template <typename Func>
static void f(const Func& func) {
func(Is...);
}
};
template <int I, int... Is, int... PIs>
struct C<int_pack<PIs...>, I,Is...> {
template <std::size_t... Idx, typename Func>
static void f_help (std::index_sequence<Idx...>, const Func& func) {
(void)std::initializer_list<int>{ (C<int_pack<PIs...,Idx>,Is...>::f(func), 0)... };
}
template <typename Func>
static void f(const Func& func) {
f_help(std::make_index_sequence<I>{}, func);
}
};
}
あなたがそうのようにこれを使用します。
C<2,3>::f([](int i, int j){
std::cout << "i " << i << " j " << j << '\n';
});
Live Demo
boost::hana
で私は嘲笑したクイックバージョンです。これを行うより良い方法があるかもしれませんが、これはあなたに何ができるかのアイデアを与えるはずです。
template <typename Func>
void unroll (const Func& func) {
func();
}
template <std::size_t I1, std::size_t... Is, typename Func>
void unroll (const Func& func) {
hana::for_each(hana::range_c<std::size_t, 0, I1>,
[&](auto x) {
unroll<Is...>([x, &func] (auto... xs) { func(x,xs...); });
});
}
回答に「boost:hana」と言っていただき、ありがとうございます。私は過去2〜3日でそれについてもっと学んできました。あなたがライブラリに慣れていて余裕がある人は、それを使用するソリューションを投稿できるかどうか疑問に思っていました。 –
@TeodorNikolov私はこのライブラリにあまり精通していません。私はそれを試して、あなたが立ち往生するなら、プロジェクトの[Gitter](https://gitter.im/boostorg/hana)の助けを求めることを勧めます。私はそこに1〜2回投稿しており、クリエイターはとてもフレンドリーです。 – TartanLlama
@TeodorNikolov私は 'boost :: hana'でどのようにできるのかという簡単なアイデアを書いていますが、おそらく自分自身で調べることをお勧めします。 – TartanLlama