首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于模板参数的另一个包创建参数包

基于模板参数的另一个包创建参数包
EN

Stack Overflow用户
提问于 2013-09-19 18:15:12
回答 1查看 1.2K关注 0票数 1

假设有几个模板类(结构),其对象构成序列--让我们称它们为N_mod(特定类的N-说明符)和特殊类,它们定义序列中的第一个元素- First_mod。除了First_mod之外,每个类都有自己的“接口生成器”-- N_builder -模板类:

代码语言:javascript
运行
复制
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
{   };

现在,我需要根据简单的规则,从适当的First_modN_mod对象的序列中生成适当的N_builders序列:

如果N_Mod(i)等于A_mod,那么targ(i) = param(i) - targ(i-1), (即N_Mod(i)等于B_mod) targ(i) = param(i) * targ(i-1)

为了清晰起见,我的草图:

代码语言:javascript
运行
复制
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,或其他一些有关整个任务的提示。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-19 20:11:38

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

代码语言:javascript
运行
复制
#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的构建器稍微容易一些

代码语言:javascript
运行
复制
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();
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18902099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档