使用模板特化添加方法

时间:2017-08-08 06:14:39

标签: c++ templates template-specialization

我有一个名为Map的哈希表容器,使用以下方法:

Value Map<Key, Value>::valueFor(const Key& key);

不幸的是,最常用的情况是Key = std::string,我们通常使用字符串文字调用方法,例如:

const Value v = map.valueFor("my_key");

我们松开了几个周期来创建std::string。因此,我想添加一个重载

Value Map<std::string, Value>::valueFor(const char* key);

Key = std::string时。我确信编译器甚至可以在编译时使用这样的签名来计算散列,这也有助于加快速度。

有没有办法在C++11中没有模板专门处理整个Map类并重写所有方法?

2 个答案:

答案 0 :(得分:1)

您可以添加另一个重载valueFor(char const * key)。如果Key不是std::string,您可能还希望使用SFINAE禁用此重载。

#include <iostream>
#include <string>
#include <type_traits>

template < typename Key, typename Value >
struct Map
{
    Value valueFor(Key const& key)
    {
        std::cout << "valueFor(const Key& key)\n";
        return Value{};
    }

    template < typename _Key = Key,
               typename = typename std::enable_if< std::is_same < _Key, std::string >::value >::type >
    Value valueFor(char const * key)
    {
        std::cout << "valueFor(char const * key)\n";
        return Value{};
    }
};

int main()
{
    Map<std::string, int> map;
    int v = map.valueFor("my_key");

    Map<int, int> other_map;
  //int v = other_map.valueFor("my_key"); // BOOM!
}

答案 1 :(得分:1)

只是削弱您的类型要求。只要表达式valueFor有效,hash<Key>(arg)就不需要(需要)关注参数的类型。

因此,您可以在其参数类型上模板valueFor,并且只需专门化您的哈希函数,并在必要时使用您的关键比较器。

例如。 (未经测试,并使用C ++ 17 string_view为简洁起见)

template <typename K>
struct Hasher
{
  static size_t hash(K const &k) { return std::hash<K>()(k); }
};
template <>
struct Hasher<std::string>
{
  static size_t hash(std::string const &s) {
    return std::hash<std::string>()(s);
  }
  static size_t hash(std::string_view const &sv) {
    return std::hash<std::string_view>()(sv);
  }
  static size_t hash(const char *cstr) {
    return std::hash<std::string_view>()({cstr});
  }
};

template <typename Key, typename Value>
template <typename KeyArg>
Value Map<Key,Value>::valueFor(KeyArg&& arg)
{
    auto hash = Hasher<Key>::hash(std::forward<KeyArg>(arg));
    // ...
}