饭后温柔

汉堡与老干妈同嚼 有可乐味
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一个基于typelist的typemap

Posted on 2014-02-23 23:06  饭后温柔  阅读(593)  评论(0编辑  收藏  举报

前面的typelist的e一个小扩展,http://www.cnblogs.com/flytrace/p/3551414.html.

可以插入pair<key_type, value_type>,然后传入key_type查找对应的value_type.

虽然是map,但仍是线性查找。基本就是一个基于typelist的体力活。

基于二叉树的typemap,可能的思路是通过编译时递增整数常量作为key_type的索引。递归层次复杂了不见得一定会比线性查找来的快。

#ifndef HI_MPL_TYPEMAP_H_INCLUDED
#define HI_MPL_TYPEMAP_H_INCLUDED

#include "TypeList.h"
#include <type_traits>


    template<typename first_, typename second_>
    struct pair
    {
        typedef first_ first;
        typedef second_ second;
    };

    //linear map
    //////////////////////////////////////////////////////////
    template<typename... TList> struct build_linear_map;

    template<typename... TList>
    struct build_linear_map
    {
        typedef typelist<TList...> type;
    };

    template<typename... TList>
    struct build_linear_map< typelist<TList...> >
    {
        typedef typelist<TList...> type;
    };

    template<typename A, typename... AList, typename B, typename... BList>
    struct build_linear_map< typelist<A, AList...>, typelist<B, BList...> >
    {
        static_assert(sizeof...(AList) == sizeof...(BList), "length is not same");
        typedef typename concat< pair<A, B>,
            typename build_linear_map< typelist<AList...>, typelist<BList...> >::type >::type type;
    };

    template<typename A, typename B>
    struct build_linear_map< typelist<A>, typelist<B> >
    {
        typedef typelist< pair<A, B> > type;
    };

    template<>
    struct build_linear_map< typelist<>, typelist<> >
    {
        typedef typelist<> type;
    };

    //////////////////////////////////////////////////////////
    template<typename Key, typename TList> struct linear_map_find;

    template<typename Key, typename T, typename... TList>
    struct linear_map_find<Key, typelist<T, TList...>>
    {
        typedef typename linear_map_find<Key, typelist<TList...> >::type type;
    };

    template<typename Key, typename Second, typename... TList>
    struct linear_map_find<Key, typelist< pair<Key, Second>, TList... >>
    {
        typedef Second type;
    };

    template<typename Key>
    struct linear_map_find<Key, nulllist>
    {
        typedef nulllist type;
    };

    //////////////////////////////////////////////////////////
    template<typename Key, typename TList> struct linear_map_find_all;

    template<typename Key, typename T, typename... TList>
    struct linear_map_find_all<Key, typelist<T, TList...>>
    {
        typedef typename linear_map_find_all<Key, typelist<TList...> >::type type;
    };

    template<typename Key, typename Second, typename... TList>
    struct linear_map_find_all<Key, typelist< pair<Key, Second>, TList... > >
    {
        typedef typename concat<Second, typename linear_map_find_all<Key, typelist<TList...> >::type >::type type;
    };

    template<typename Key>
    struct linear_map_find_all<Key, nulllist>
    {
        typedef nulllist type;
    };

    //////////////////////////////////////////////////////////
    template<typename T, typename... TList> struct linear_map_add;

    template<typename T, typename... TList>
    struct linear_map_add< T, typelist<TList...> >
    {
        typedef typename concat<T, typelist<TList...> >::type type;
    };

    template<typename Key, typename NewValue, typename... TList>
    struct linear_map_add<Key, NewValue, typelist<TList...> >
    {
        typedef typename concat<pair<Key, NewValue>, typelist<TList...> >::type type;
    };

    //////////////////////////////////////////////////////////
    template<typename T, typename... TList> struct linear_map_insert;

    template<typename T, typename... TList>
    struct linear_map_insert<T, typelist<TList...> >
    {
        static_assert( std::is_same<
                      typename linear_map_find<typename T::first, typelist<TList...> >::type,
                      nulllist>::value, "key already exist");
        typedef typename concat<T, typelist<TList...> >::type type;
    };

    template<typename First, typename Second, typename... TList>
    struct linear_map_insert<First, Second, typelist<TList...> >
    {
        static_assert( std::is_same<
                      typename linear_map_find<First, typelist<TList...> >::type,
                      nulllist>::value, "key already exist");
        typedef typename concat<pair<First, Second>, typelist<TList...> >::type type;
    };


    //////////////////////////////////////////////////////////
    template<typename T, typename... TList> struct linear_map_replace;

    template<typename T, typename H, typename... TList>
    struct linear_map_replace<T, typelist<H, TList...> >
    {
        typedef typename concat<H, typename linear_map_replace<T, typelist<TList...> >::type>::type type;
    };

    template<typename Key, typename NewValue, typename OldValue, typename... TList>
    struct linear_map_replace<pair<Key, NewValue>, typelist<pair<Key, OldValue>, TList...> >
    {
        typedef typename concat<pair<Key, NewValue>, typelist<TList...> >::type type;
    };

    template<typename T>
    struct linear_map_replace<T, nulllist>
    {
        typedef nulllist type;
    };

    template<typename Key, typename NewValue, typename... TList>
    struct linear_map_replace<Key, NewValue, typelist<TList...> >
    {
        typedef typename linear_map_replace<pair<Key, NewValue>, typelist<TList...> >::type type;
    };

    //////////////////////////////////////////////////////////
    template<typename T, typename... TList> struct linear_map_earse;

    template<typename T, typename H, typename... TList>
    struct linear_map_earse<T, typelist<H, TList...> >
    {
        typedef typename concat<H, typename linear_map_earse<T, typelist<TList...> >::type>::type type;
    };

    template<typename Key, typename Value_, typename... TList>
    struct linear_map_earse<Key, typelist<pair<Key, Value_>, TList...> >
    {
        typedef typelist<TList...> type;
    };

    template<typename T>
    struct linear_map_earse<T, nulllist>
    {
        typedef nulllist type;
    };


    //////////////////////////////////////////////////////////
    template<typename T, typename... TList> struct linear_map_earse_all;

    template<typename T, typename H, typename... TList>
    struct linear_map_earse_all<T, typelist<H, TList...> >
    {
        typedef typename concat<H, typename linear_map_earse_all<T, typelist<TList...> >::type>::type type;
    };

    template<typename Key, typename Value_, typename... TList>
    struct linear_map_earse_all<Key, typelist<pair<Key, Value_>, TList...> >
    {
        typedef typename linear_map_earse_all<Key, typelist<TList...>>::type type;
    };

    template<typename T>
    struct linear_map_earse_all<T, nulllist>
    {
        typedef nulllist type;
    };


    //////////////////////////////////////////////////////////
    template<typename T, typename... TList> struct linear_map_no_duplicate;

    template<typename T, typename...TList>
    struct linear_map_no_duplicate< typelist<T, TList...> >
    {
    private:
        typedef typename linear_map_no_duplicate< typelist<TList...> >::type inner;
        typedef typename linear_map_earse<typename T::first, inner>::type inner_result;
    public:
        typedef typename concat<T, inner_result>::type type;
    };

    template<>
    struct linear_map_no_duplicate< nulllist >
    {
        typedef nulllist type;
    };


#endif // HI_MPL_TYPEMAP_H_INCLUDED

例子:

#include <iostream>
#include "TypeTraits.h"
#include "TypeList.h"
#include "TypeMap.h"


int main()
{
    typedef build_linear_map<
        pair<int, float>,
        pair<float, double>,
        pair<bool, char>
    >::type testmap;

    typedef typelist<int, float, bool> keylist;
    typedef typelist<float, double, char> valuelist;
    typedef typelist<float, bool, char> newvaluelist;
    typedef build_linear_map<keylist, valuelist>::type testmapcopy;
    typedef build_linear_map<keylist, newvaluelist>::type testmapnew;

    typedef build_linear_map<
        pair<int, float>,
        pair<float, double>,
        pair<bool, char>,
        pair<int, char>
    >::type testmap2;

    typedef build_linear_map<
        pair<int, float>,
        pair<float, double>,
        pair<bool, char>,
        pair<double, char>
    >::type testmap3;

    typedef build_linear_map<
        pair<int, float>,
        pair<float, double>,
        pair<bool, char>,
        pair<double, char>,
        pair<double, int>
    >::type testmap4;

    bool b;

    b = std::is_same<linear_map_find<float, testmap>::type, double>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<testmapcopy, testmap>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<linear_map_insert<pair<short, long>, testmapcopy>::type,
                    linear_map_add<pair<short, long>,testmap>::type>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<linear_map_replace<pair<float, bool>, testmap>::type, testmapnew>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<linear_map_find_all<int, testmap2>::type, typelist<float, char>>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<linear_map_earse<double, testmap3>::type, testmap>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<linear_map_earse_all<double, testmap4>::type, testmap>::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<linear_map_no_duplicate<testmap4>::type, testmap3>::value;
    std::cout << "is same: " << b << std::endl;

    return 0;
}