【问题标题】:Specialize hashmap template专门化哈希图模板
【发布时间】:2011-06-25 10:35:53
【问题描述】:

我在 C++ 中使用 hash_map 并想为其提供一个简化的类型名称:

密钥类型和哈希函数始终相同。

stdext::hash_map<std::string, [MAPPED TYPE], CStringHasher>

但是,我真的不想在每次声明将字符串映射到类型 X 的哈希映射时都写下所有这些。

  • 我可以写一个模板或宏来简化这个吗?

所以上面的声明看起来像:

template<typename T> StringHashmap = stdext::hash_map<std::string, T, CStringHasher>

StringHashmap<int> mapA; //Maps std::string to int
StringHashamp<bool> mapB; //Maps std::string to bool

【问题讨论】:

    标签: c++ templates hash hashmap std


    【解决方案1】:

    正如其他人所说,如果您可以使用 C++0x,模板别名是必经之路:

    template < typename MappedType >
    using StringHashMap = stdext::hash_map< std::string, MappedType, CStringHasher >;
    
    StringHashMap< int > mapA;
    StringHashMap< bool > mapB;
    

    (正如@MSalters 所说,如果你有可用的 C++0x,你可能应该使用std::unordered_map。)

    否则,您仍然可以使用通常的解决方法,即定义一个包含 typedef 的类模板:

    template < typename MappedType >
    struct StringHashMap
    {
        typedef stdext::hash_map< std::string, MappedType, CStringHasher > type;
    };
    
    StringHashMap< int >::type mapA;
    StringHashMap< bool >::type mapB;
    

    此解决方案的一个缺点(在 SO 上产生 许多 问题)是您有时需要在 StringHashMap&lt; T &gt;::type 前面加上 typename 关键字,以便向编译器断言这name 有效地表示一个类型。我不会在这个答案中详述这个主题,您可以查看this FAQ,尤其是接受的答案,以获取更多信息。 (感谢@sbi 提出这个问题。)

    【讨论】:

    • +1 这是一个比我更好的答案。我将不得不记住这个技巧。
    • 请注意,StringHashMap&lt;T&gt;::type 在模板中使用时需要限定为类型名称,其中T 是(或依赖于)模板参数:typename StringHashMap&lt;T&gt;::type。 SO上有一个FAQ entry for that。你可能想在这个问题上多说几句。不过,+1 是一个很好的答案。
    • 如果你有 C++0x,你会使用 std::unordered_map 而不是 stdext::hash_map
    • @sbi @MSalters:我编辑了答案以包含您的评论,感谢 cmets。
    【解决方案2】:

    在当前版本的 C++ (C++03) 中,确实没有一个好的方法可以做到这一点。您可以尝试类似

    #define StringHashMap(type) stdext::hash_map<std::string, type, CStringHasher>
    

    但是如果你尝试指定一个带有逗号的模板类型,你会遇到麻烦,像这样:

    StringHashMap(pair<int, string>) myMap; // Error!
    

    这会失败,因为预处理器会将其标记为

    StringHashMap((pair<int), (string>)) myMap; // Error!
    

    这不是你想要的。不过,如果你不打算做这样的事情,你应该没问题。您也可以使用typedefs 来绕过它:

    typedef pair<int, int> IntPair;
    StringHashMap(IntPair) myMap; // Okay
    

    如果您允许使用 C++0x 功能,则可以使用模板声明,如下所示:

    template <typename T>
        using StringHashMap = stdext::hash_map<std::string, T, CStringHasher>;
    

    不幸的是,C++03 没有像这样的“模板类型定义”功能,因此您必须使用较新的编译器,并且没有那么好的可移植性保证。

    嘿,等一下!我的名字是templatetypedef,这是我在 Stack Overflow 上第一次在答案中写下这个短语!你刚刚让我的夜晚。 :-)

    【讨论】:

    • +1 表示有合适的用户名来回答这个问题。
    • 我认为您需要在 using 声明中删除 StringHashMap 之后的 &lt;T&gt; 。关于宏参数中逗号问题的好评论。
    【解决方案3】:

    如果您使用的是 C++ 0x,那么模板 typedef 就是专门为做这种事情而设计的:

    http://en.wikipedia.org/wiki/C%2B%2B0x#Template_aliases

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-15
      相关资源
      最近更新 更多