收拾好你的類型轉換成一個列表:
template<typename... Ts>
struct type_list {};
使用該列表和參數包拆包,以創建隊列的std::array
。如果你想排隊,他們將需要在tuple
。
上面的列表意味着索引和類型之間的雙射。每種類型的實例都會返回索引,您可以使用該索引來拾取隊列(在數組中,很容易 - 在tuple
中,需要更多工作)。
的index_of
traits類,找到一種T
的一個type_list<Ts...>
指數:
template<typename T, typename list, typename=void>
struct index_of {};
template<typename T, typename T0, typename... Ts>
struct index_of<T, type_list<T0, Ts...>,
typename std::enable_if<std::is_same<T, T0>::value>::type
> : std::integral_constant<size_t, 0>
{};
template<typename T, typename T0, typename... Ts>
struct index_of<T, type_list<T0, Ts...>,
typename std::enable_if<!std::is_same<T, T0>::value>::type
> : std::integral_constant<size_t,
index_of<T, type_list<Ts...>>::value+1>
{};
可能實現CRTP基於「消息幫手」同時實現GetTypeIndex
,並確保你的類型是在中央消息列表。
這需要C++ 11,在C++ 03中這是非常困難和更有限的。一個C++ 11編譯器也可以處理100多種類型,而不需要額外的模板元編程(至少在理論上有嚴重的元編程,1000或更多),而C++ 03編譯器即使具有強大的元編程庫也可能受限於10種類型。
請注意,這種方法的一個優點是,您理論上可以完全廢除抽象父類,或者至少使用接口(爲什麼應允許人們發送抽象消息?)。您只能發送實際的具體消息類型。這又需要更多的工作(創建使用CRTP的pack-expanded繼承樹來獲取隊列的位置)。
struct MessageBase {
virtual size_t GetTypeIndex() const = 0;
};
template<typename D, typename List>
struct MessageHelper: public MessageBase {
static_assert(std::is_base_of< MessageHelper<D,List>, D >::value, "MessageHelper<D> must be inherited from by D");
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D const*>(this); }
virtual size_t GetTypeIndex() const final override {
return index_of<D,List>::value;
}
};
struct A_Queue {
std::deque< std::unique_ptr<MessageBase> > data;
};
template<typename type_list>
struct MessageQueues;
template<typename... Ts>
struct MessageQueues<type_list<Ts...>> {
std::array< A_Queue, sizeof...(Ts) > queues;
void Enqueue(std::unique_ptr<MessageBase> msg) {
size_t index = msg->GetTypeIndex();
queues[ index ].data.push-back(std::move(msg));
}
};
對於嚴重粗略的草案實施。
謝謝!我已經採用了你提到的一些東西,雖然沒有尋求完整的元編程解決方案,但我想到了一個使用模板和運行時的中間解決方案。 – Edgepo1nt