Skip to content

Dispatch based on constant

关于constant,参见C++\Language-reference\Expressions\Constant-expressions

实现方式有:

1) enum dispatch

enum dispatch / enum in TMP

我记得在TMP中,有多处是使用到了enum的,需要整理一下。

Enum dispatch: Enum + enable_if

为每个trait class添加一个表示其类型的常量,然后添加判断条件来判断它属于哪种类型?

比如我定义有三种类型:

// 服务类型
enum EServiceType
{

   TradeService=1;//交易类服务 
   QueryService=2;//查询类服务
};
// 某个服务
struct FooService
{
    constexpr static int ServiceType = EServiceType::TradeService;
};
// 判断是否是交易类服务
constexpr bool IsTradeService(EServiceType ServiceType)
{
    return ServiceType == TradeService;
}

template<class ServiceTraitType>
auto ReqService()->typename std::enable_if<IsTradeService(ServiceTraitType::ServiceType), int>::type
{

}

我的实践

#include <type_traits>
#include <iostream>

/**
* 消息类型
*/
enum MsgType
{
    MSG_TRADE = 0x1,                    /**>主机 交易 */
    MSG_QUERY = 0x2,                    /**> 主机查询 */
};


/**
 */
struct MsgProtocol
{
    template<int ServiceMsgType>
    static auto Pack()->typename std::enable_if<ServiceMsgType==MsgType::MSG_TRADE, void>::type
    {
        std::cout<<"trade msg"<<std::endl;
    }
template<int ServiceMsgType>
    static auto Pack()->typename std::enable_if<ServiceMsgType==MsgType::MSG_QUERY, void>::type
    {
        std::cout<<"query msg"<<std::endl;
    }
};


int main()
{
MsgProtocol::Pack<MsgType::MSG_TRADE>();
MsgProtocol::Pack<MsgType::MSG_QUERY>();

}

Enum specialization

gist kimgea/cpp-traits.cpp

#include <vector>
#include <list>
#include <set>


enum class insert_method_enum{general, push_back, push_front};


// Main template insert helper with its temlate specialications
template<insert_method_enum i>
struct insert_selector
{
    template<typename t, typename v>
    static void insert(t& object, v value)
    {
        object.insert(object.end(), value);
    }
};

template<>
struct insert_selector<insert_method_enum::push_back>
{
    template<typename t, typename v>
    static void insert(t& object, v value)
    {
        object.push_back(value);
    }
};
template<>
struct insert_selector<insert_method_enum::push_front>
{
    template<typename t, typename v>
    static void insert(t& object, v value)
    {
        object.push_front(value);
    }
};


// type traits
template<typename t, typename v>
struct insert_type {
    static const insert_method_enum value = insert_method_enum::general;
};

template<typename v>
struct insert_type<std::vector<v>, v> {
    static const insert_method_enum value = insert_method_enum::push_back;
};

template<typename v>
struct insert_type<std::list<v>, v> {
    static const insert_method_enum value = insert_method_enum::push_front;
};



// Function used by end user
template<typename t, typename v>
void insert(t& object, v value)
{
    insert_selector<insert_type<t, v>::value>::insert(object, value);
}

// Extra function to make the end user able to overwrite pre made specialications
template<insert_method_enum i, typename t, typename v>
void insert(t& object, v value)
{
    insert_selector<i>::insert(object, value);
}


int main()
{
    std::vector<int> vector;
    insert(vector, 1);  // Specialized - vector.push_back(1)


    std::list<int> list;
    insert(list, 1);    // Specialized - list.push_front(1)

    std::set<int> set;
    insert(set, 1); // General - set.insert(set.end(), 1);  



    std::list<int> list2;
    insert<insert_method_enum::push_back>(list2, 1);    

    return 0;
}
// g++ --std=c++11 test.cpp