c++模版学习(typelist)2021-03-05

本文介绍了一种使用模板元编程实现类型列表(typelist)的方法,包括基本操作如获取首个类型、计算列表大小、移除首个类型等,并展示了如何通过递归模板特化实现更复杂的功能如查找指定索引的类型、获取最大类型、反转类型列表等。

 

namespace tplt
{
    //基本的操作接口
    template <typename ... T>
    class typelist
    {

    };

    template <typename TPLT>
    class front;

    template <typename fisrt, typename ...other>
    class front<typelist<fisrt, other...>>
    {
    public:
        using type = fisrt;


    };

    template <typename TPLT>
    class size;

    template <typename ...args>
    class size<typelist<args...>>
    {
    public:
        static inline size_t value = sizeof...(args);
    };

    template <typename TPLT>
    class pop_front;

    template <typename fisrt, typename ...other>
    class pop_front<typelist<fisrt, other...>>
    {
    public:
        using type = typelist<other...>;


    };

    template <typename TPLT, typename NewElem>
    class push_front;



    template <typename ...Elem, typename NewElem>
    class push_front<typelist<Elem...>, NewElem>
    {
    public:
        using type = typelist<NewElem, Elem...>;
    };


    template <typename TPLT, typename NewElem>
    class push_back;

    template <typename ...Elem, typename NewElem>
    class push_back<typelist<Elem...>, NewElem>
    {
    public:
        using type = typelist<Elem..., NewElem>;
    };


    template <typename TPLT, typename NewElem>
    class replace_front;


    template <typename fisrt, typename ...other, typename NewElem>
    class replace_front<typelist<fisrt, other...>, NewElem>
    {
    public:
        using type = typelist<NewElem, other...>;
    };


    template <typename TPLT>
    class is_empty
    {
    public:
        static inline const bool value = false;
    };


    template <>
    class is_empty<typelist<>>
    {
    public:
        static inline const bool value = true;
    };
    //扩展
    //找index的类型
    template <typename TPLT, unsigned int index>
    class find :public find<typename pop_front<TPLT>::type, index -1>
    {

    };
    template <typename TPLT>
    class find<TPLT, 0> :public front<TPLT> 
    {

    };
    //找到最大的元素
    template <typename TPLT>
    class get_maxsize_type
    {
    private:
        //TPLT中的第一个元素
        using tl_first_elem = typename front<TPLT>::type;
        //TPLT中去掉第一个元素
        using tl_remain = typename pop_front<TPLT>::type;
        //递 归下去的get_maxsize_type中的typelist(模版参数)的第一个元素
        using t1_first_elem_rec = typename get_maxsize_type<tl_remain>::type;
    public:
        using type = typename std::conditional<
            sizeof(tl_first_elem) >= sizeof(t1_first_elem_rec),
            tl_first_elem,
            t1_first_elem_rec>::type;
    };

    template<>
    class get_maxsize_type<typelist<>>
    {
    public:
        using type = char;
    };


    //反转(reverse)
    template <typename TPLT, bool = is_empty<TPLT>::value>
    class reverse;

    //有元素
    template <typename TPLT>
    class reverse<TPLT, false>
    {
        //TPLT中的第一个元素
        using tl_first_elem = typename front<TPLT>::type;

        using tl_result_rec = typename reverse<
                                    typename pop_front<TPLT>::type>::type;

    public:
        using type = typename push_back<tl_result_rec, tl_first_elem>::type;
    };
    //无元素
    template <typename TPLT>
    class reverse<TPLT, true>
    {
    public:
        using type = typename TPLT;//此时为typelist<>
    };
}
using TPL_NM1 = tplt::typelist<int, double, float, char, bool>;
using TPL_NM2 = tplt::typelist<>;


namespace tplt2
{
    class  NullTypelist{};
    template <typename T, typename U = NullTypelist>
    class Typelist
    {
    public:
        using Head = T;
        using Tail = U;

    private:
    };

    template<typename TPLT>
    class front
    {
    public:
        using type = typename TPLT::Head;
    };

    template <typename TPLT>
    class size;

    template<>
    class size<NullTypelist>
    {
    public:
        static inline size_t value = 0;
    };

    template<typename T, typename U>
    class size<Typelist<T, U>>
    {
    public:
        static inline size_t value = size<U>::value + 1;
    };


    template <typename TPLT>
    class pop_front
    {
    public:
        using type = typename TPLT::Tail;
    };

    template <typename TPLT, typename NewElem>
    class push_front
    {
    public:
        using type = Typelist<NewElem, TPLT>;
    };
    template <typename TPLT, typename NewElem>
    class push_back
    {
    public:
        using type = Typelist<TPLT, NewElem>;
    };

    template <typename TPLT>
    class is_empty
    {
    public:
        static inline const bool value = false;
    };
    template <>
    class is_empty<NullTypelist>
    {
    public:
        static inline const bool value = true;
    };

    //template <typename TPLT, unsigned int index>
    //class find : public find<typename pop_front<TPLT>::type, index - 1>
    //{
    //};

    //template <typename TPLT>
    //class find<TPLT, 0> : public front<TPLT>
    //{
    //public:

    //};


    template <typename TPLT, unsigned int index>
    class find;
    template <typename Head, typename Tail>
    class find<Typelist<Head, Tail>, 0>
    {
    public:
        using type = Head;
    };
    template <typename Head, typename Tail, unsigned int index>
    class find<Typelist<Head, Tail>, index>
    {
    public:
        using type = typename find<Tail, index - 1>::type;
    };
    

    template <typename TPLT, unsigned int index, typename defaultType = NullTypelist>
    class find_nostrict
    {
    public:
        using type = defaultType;
    };

    template <typename Head, typename Tail, typename defaultType>
    class find_nostrict<Typelist<Head, Tail>, 0, defaultType>
    {
    public:
        using type = Head;
    };
    template <typename Head, typename Tail, unsigned int index, typename defaultType>
    class find_nostrict<Typelist<Head, Tail>, index, defaultType>
    {
    public:
        using type = typename find_nostrict<Tail, index -1, defaultType>::type;
    };


    template <typename Args>
    class TestTPCloass
    {
    public:
        using arg1 = typename find_nostrict<Args, 0>::type;
        using arg2 = typename find_nostrict<Args, 1>::type;
        using arg3 = typename find_nostrict<Args, 2>::type;
        void func(arg1 v1, arg2 v2)
        {
            cout << v1 + v2 << endl;
        }
    };
}
#define MAC_TYPELIST1(T1)               tplt2::Typelist<T1, tplt2::NullTypelist>
#define MAC_TYPELIST2(T1, T2)           tplt2::Typelist<T1, MAC_TYPELIST1(T2)>
#define MAC_TYPELIST3(T1, T2, T3)       tplt2::Typelist<T1, MAC_TYPELIST2(T2, T3)>
#define MAC_TYPELIST4(T1, T2, T3, T4)   tplt2::Typelist<T1, MAC_TYPELIST3(T2, T3, T4)>

using TPL_NM3 = MAC_TYPELIST3(int, double, char);

int main()
{
    std::cout << typeid(tplt::front<TPL_NM1>::type).name() << std::endl;
    std::cout << tplt::size<TPL_NM1>::value << std::endl;
    std::cout << typeid(tplt::pop_front<TPL_NM1>::type).name() << std::endl;
    std::cout << typeid(tplt::push_front<TPL_NM1, bool>::type).name() << std::endl;
    std::cout << typeid(tplt::push_back<TPL_NM1, bool>::type).name() << std::endl;
    std::cout << typeid(tplt::replace_front<TPL_NM1, bool>::type).name() << std::endl;
    std::cout << typeid(tplt::is_empty<TPL_NM1>::value).name() << std::endl;
    std::cout << typeid(tplt::find<TPL_NM1, 2>::type).name() << std::endl;
    std::cout << typeid(tplt::get_maxsize_type<TPL_NM1>::type).name() << std::endl;
    std::cout << typeid(tplt::reverse<TPL_NM1>::type).name() << std::endl;

    cout << typeid(tplt2::front<TPL_NM3>::type).name() << endl;
    cout << tplt2::size<TPL_NM3>::value << endl;
    cout << typeid(tplt2::pop_front<TPL_NM3>::type).name() << endl;
    cout << typeid(tplt2::push_back<TPL_NM3, bool>::type).name() << endl;

    cout << tplt2::is_empty<TPL_NM3>::value << endl;

    cout << typeid(tplt2::find<TPL_NM3, 1>::type).name() << endl;

    cout << typeid(tplt2::find_nostrict<TPL_NM3, 1>::type).name() << endl;
    cout << typeid(tplt2::find_nostrict<TPL_NM3, 5>::type).name() << endl;

    tplt2::TestTPCloass<TPL_NM3> obj;
    obj.func(18, 19);
    
    return 0;
}

get_maxsize_type 展开关系如下图

reverse//如下

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值