gpt4 book ai didi

c++ - 根据模板参数中的另一个包创建参数包

转载 作者:行者123 更新时间:2023-11-30 01:57:17 26 4
gpt4 key购买 nike

假设有几个模板类(结构),其对象形成序列 - 让我们称它们为 N_mod(N - 特定类的说明符),以及定义第一个元素的特殊类序列 - First_mod。每个类,除了First_mod,都有自己的“接口(interface)构建器”——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_modN_mod 对象序列:

if N_Mod(i) equals A_mod then targ(i) = param(i) - targ(i-1),

else(i.e. N_Mod(i) equals 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,或为整个任务提供一些其他提示。

最佳答案

首先,我将转储(编译)解决方案:

#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();
}

关于c++ - 根据模板参数中的另一个包创建参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18902099/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com