2016-09-22 6 views
3

だから私はこれが可能なのかどうかはわかりません。コンパイル時にマップを静的にチェックしていますか?

とにかく、静的なconstマップ(または類似のもの)をコンパイル時にチェックして、一致する値(この場合は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リストはタイプがリストにあるかどうかを調べるだけです。ちょうど一見で、私はメンテナンスの悪夢になることなく、私が帰りIDをつかむことができるとは思わない。 – mascoj

+0

が正しいのですが、型の型を使用して型のIDを取得できます。 – imreal

答えて

4

マップをタイプとして格納します。

タイプを使用して、ランタイム・タイプIDマップを作成します。ここで

は、あなたのコンパイル時のマップのキーと値のペアです:

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

関連する問題