c++ - 在编译时静态检查 map ?

标签 c++ templates visual-studio-2012 std

因此,我将在这个问题前加上我不确定这是否可能。

无论如何,我正在尝试在编译时检查静态常量映射(或类似的东西)以验证它是否具有匹配值(在本例中为 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 时,我保证在构建时有一个值,并且不必依赖运行时恶作剧,因为这是一个由许多人修改的大型代码库(我不能阻止他们在运行时做坏事)。其他实现或任何帮助将不胜感激。谢谢。

最佳答案

将 map 存储为一种类型。

使用该类型构建您的运行时 typeid 映射。

这是编译时映射的键值对:

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

然后我们根据它制作一张 map :

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 >{}>{};
  }
};

此 map 可以生成您选择的类型的运行时 map 。

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 .

关于c++ - 在编译时静态检查 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39647527/

相关文章:

c++ - 如何处理 C++ 内联 + 模板上下文中的警告?

visual-studio-2012 - 异步方法的代码覆盖率

c++ - poly2tri getTriangles() 和 getMap() 有什么区别?

c++ - 如何使用 gettimeofday() 获取运行时间?

c# - 将 WPF 控件类作为模板类

visual-studio - 从命令行将文件添加到 Visual Studio C++ 项目

visual-studio - Visual Studio 2012 Express 桌面的限制

java - collect2.exe : error: ld returned 1 exit status while compiling C++ code with gradle 2. 3

c++ - 预期的主要表达之前

c++ - 如何根据模板中的类型编译函数?