假设有几个模板类(结构),其对象形成序列 - 让我们称之为 N_mod (特定类的N - 说明符)和特殊类,它们定义序列中的第一个元素 - First_mod 。除 First_mod 外,每个类都有自己的"界面构建器" - N_builder - 模板类:
template<int targ>
struct First_mod //First element in sequence - without appropriate builder interface
{ };
//Let's consider two types of N_mod - A_mod and B_mod
template<int targ, int param>
struct A_mod
{ };
template<int param>
struct A_builder//Builder for A_mod objects
{ };
template<int targ, int param>
struct B_mod
{ };
template<int param>
struct B_builder//Builder for B_mod objects
{ };
现在我需要根据简单的规则从适当的 N_builders 的现有顺序生成 First_mod 和 N_mod 对象的序列:
如果 N_Mod(i) 等于 A_mod 那么 targ(i) = param(i) - targ(i-1),
else (即 N_Mod(i) 等于 B_mod )targ(i)= param(i) * targ(i-1)
为了清晰起见,我的草图:
template<typename...builders>
struct mod_seq_gen
{
typedef /*generated First_mod, A_mod and B_mod sequence pack. How to do it?*/ modseq;
};
template<typename...builders>
struct Container
{
std::tuple</*here must be mod-sequence generator that creates
mod parameters pack and unpacks them:*/
mod_seq_gen<builders...>::modseq
> mod_sequence;
};
int main()
{
/*In this case must be generated next sequence and stored in
* mod_sequence tuple:
* First_mod<3> - A_mod<5-3, 5> - B_mod<2*(5-3), 2>
*/
Container<First_mod<3>, A_builder<5>, B_builder<2>> obj;
}
我要求帮助实施 mod_seq_gen ,或者整个任务的其他一些提示。
答案 0 :(得分:4)
首先,我将转储(编译)解决方案:
#include <tuple>
#include <utility>
#include <iostream>
template<int targ>
struct First_mod //First element in sequence - without appropriate builder interface
{ void print() { std::cout << "First_mod["<<targ<<"]" << std::endl; } };
//Let's consider two types of N_mod - A_mod and B_mod
template<int targ, int param>
struct A_mod
{ void print() { std::cout << "A_mod["<<targ<<", "<<param<<"]" << std::endl; } };
template<int param>
struct A_builder//Builder for A_mod objects
{
// publish the template parameter (not necessary)
static const int param_value = param;
// provide a way to compute the current targ
static constexpr int calc_targ(int prev_targ)
{
return param - prev_targ;
}
// provide a way to build the type
template < int targ >
using type = A_mod<targ, param>;
};
template<int targ, int param>
struct B_mod
{ void print() { std::cout << "B_mod["<<targ<<", "<<param<<"]" << std::endl; } };
template<int param>
struct B_builder//Builder for B_mod objects
{
static const int param_value = param;
static constexpr int calc_targ(int prev_targ)
{
return prev_targ * param;
}
template < int targ >
using type = B_mod<targ, param>;
};
// just a helper, wonder if there's something in the Standard Library o.O
template < typename... Tuples >
using tuple_cat_types = decltype(tuple_cat( std::declval<Tuples>()... ));
// the generator of the tuple
template < typename TFirst_mod, typename... TBuilders >
struct gen;
// restrict the first type to a specialization of `First_mod`
// isn't necessary, strictly speaking. We just need the first targ.
// Could as well require a nested `static const int targ = ..;`
template < int first_targ, typename... TBuilders >
struct gen < First_mod<first_targ>, TBuilders... >
{
// recursive helper for the types to be built
// general case for no template arguments in the pack
template < int prev_targ, typename... TBuilders2 >
struct helper { using type = std::tuple<>; };
// specialized case for recursion
// note: the recursion here occurs as a nested typedef, not inheritance
// (simplifies use of calculated targ)
template < int prev_targ, typename TBuilder, typename... TBuilders2 >
struct helper<prev_targ, TBuilder, TBuilders2...>
{
// build type using builder
static const int targ = TBuilder::calc_targ(prev_targ);
using built_type = typename TBuilder::template type<targ>;
// recurse
using further_types = typename helper<targ, TBuilders2...>::type;
// concatenate tuple
using type = tuple_cat_types<std::tuple<built_type>, further_types>;
};
// concatenate tuple with First_mod
using type = tuple_cat_types<std::tuple<First_mod<first_targ>>,
typename helper<first_targ, TBuilders...>::type>;
};
int main()
{
gen<First_mod<3>, A_builder<5>, B_builder<2>>::type x;
static_assert(std::tuple_size<decltype(x)>::value == 3, "!");
std::get<0>(x).print();
std::get<1>(x).print();
std::get<2>(x).print();
}
使用First_mod
的构建器稍微容易一些:
template<int param>
struct First_builder
{
static constexpr int calc_targ(int /* discarded */)
{
return param;
}
template < int targ >
using type = First_mod<targ>;
};
/* ... */
// the generator of the tuple
template < int prev_targ, typename... TBuilders >
struct gen
{ using type = std::tuple<>; };
template < int prev_targ, typename TBuilder, typename... TBuilders2 >
struct gen<prev_targ, TBuilder, TBuilders2...>
{
// build type using builder
static const int targ = TBuilder::calc_targ(prev_targ);
using built_type = typename TBuilder::template type<targ>;
// recurse
using further_types = typename gen<targ, TBuilders2...>::type;
// concatenate tuple
using type = tuple_cat_types<std::tuple<built_type>, further_types>;
};
int main()
{
const int discarded = 0;
gen<discarded, First_builder<3>, A_builder<5>, B_builder<2>>::type x;
static_assert(std::tuple_size<decltype(x)>::value == 3, "!");
std::get<0>(x).print();
std::get<1>(x).print();
std::get<2>(x).print();
}