2016-09-22 69 views
3

所以,我將以這個問題作爲序言,我不確定這是否可能。在編譯時靜態檢查地圖?

無論如何,我試圖在編譯時檢查一個靜態常量映射(或類似的東西)來驗證它將有一個匹配的值(在這種情況下是一個id)。具體來說,我目前有這樣的東西壞了(但它不編譯):

template<typename T> 
struct TypeMapChecker 
{ 
    static const std::map<std::type_info, MessageID> type_map; 
    static const bool contains = (type_map.count(typeid(T)) > 0); 
} 

template<typename T> 
const std::map<std::type_info, MessageID> TypeMapChecker<T>::type_map = { 
    { typeid(ClassA), MESSAGE_A_ID }, 
    { typeid(ClassB), MESSAGE_B_ID } 
}; 

.......... 

template<typename T0, typename T1> 
class MessagePair 
{ 
    static const bool t0Has = TypeMapChecker<T0>::contains; 
    static const bool t1Has = TypeMapChecker<T1>::contains; 
    static_assert (t0Has && t1Has, "I'M ASSERTING MY AUTHORITY, YOU MALIGNANT CODERS"); 
} 

就是這樣的東西。這不建,因爲「預計常量表達式」上:

static const bool contains = (type_map.count(typeid(T)) > 0); 

只是想驗證,當我在MessagePair訪問type_map我保證在構建時的值,而不必依賴因爲這是一個很大的代碼庫(我無法阻止它們在運行時做壞事)修改了運行時的惡意代碼。其他實現或任何幫助將不勝感激。謝謝。

+1

你不能用地圖來做到這一點,但是如果你想要一個編譯時間類型容器和查詢成員資格,你可以使用一個類型列表。 http://loki-lib.sourceforge.net/html/a00681.html – imreal

+0

@imreal所以這個列表只是查找類型是否在列表中的權利?只是一目瞭然,我不認爲我能夠在沒有成爲維護噩夢的情況下獲得回報。 – mascoj

+0

正確,但是您可以使用類型特徵來獲取類型的標識。 – imreal

回答

4

將地圖存儲爲類型。

使用該類型來構建您的運行時typeid映射。

這裏是你的編譯時間圖的鍵值對:

template<class Key, class Value> 
struct entry { 
    using key=Key; 
    using value=Value; 
}; 

然後我們從它製作地圖:

template<class T> struct tag_t{using type=T; constexpr tag_t(){};}; 
template<class T> constexpr tag_t<T> tag{}; 

template<class...Entries> 
struct compile_time_map:Entries... { 
    template<class Key> 
    struct lookup { 
    template<class Value> 
    constexpr tag_t<Value> operator()(entry<Key, Value> const&) const { return {}; } 
    }; 
    template<class Key> 
    constexpr 
    std::result_of_t< lookup<Key>(compile_time_map) > operator()(tag_t<Key>) const { 
    return {}; 
    } 
    template<class...Key> 
    constexpr std::false_type operator()(tag_t<Key...>) const { 
    return {}; 
    } 
    template<class MessageID> 
    std::map< std::type_index, MessageID > make_map() const { 
    return { {typeid(typename Entries::key), typename Entries::value{}}... }; 
    } 

    template<class Key> 
    constexpr auto has(tag_t<Key> ={}) const { 
    return std::integral_constant<bool, !std::is_same< std::result_of_t< compile_time_map(tag_t<Key>)>, std::false_type >{}>{}; 
    } 
}; 

這張地圖可以生成一個運行時間圖您選擇的一種類型。

using ID=unsigned; 

template<class T, ID id> 
using make_entry = entry<T, std::integral_constant<ID, id>>; 

using ctm = compile_time_map< 
    make_entry< int, 7 >, 
    make_entry< double, 3 >, 
    make_entry< std::string, (unsigned)-1 > 
>; 

auto rtm = ctm{}.make_map<ID>(); 

我們可以使用ctm{}(tag<int>)進行編譯時查找。我們可以使用rtm[ typeid(int) ]進行運行時查詢。

我們可以在編譯時用ctm{}.has<int>()ctm{}.has(tag<int>)檢查是否有條目。

live example