所以,我会在这个问题前面加上我不确定这是否可能。
无论如何,我试图在编译时检查静态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时,我保证在构建时有一个值,并且不必依赖于运行时的恶作剧,因为这是一个由许多人修改的大型代码库(我不能阻止他们在运行时做坏事。其他实现或任何帮助将不胜感激。感谢。
答案 0 :(得分: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> )
检查编译时是否有条目。