c++ - 具有覆盖运算符或外部仿函数的可散列类型

标签 c++ templates functor unordered-set

std::unordered_set 中使用自定义类型我不得不选择。

1) 执行==我的类型和专业的运算符 std::hash

struct MyType {
    int x;

    bool operator==(const MyType& o) {
        return this.x == o.x;
    }
};

namespace std
{
template<>
struct hash<MyType> {
    size_t operator()(const MyType& o) const {
        return hash<int>()(o.x);
    }
};
}

std::unordered_set<MyType> mySet;

或者2),提供仿函数类:
struct MyTypeHash {
    size_t operator()(const MyType& o) const {
        return std::hash<int>()(o.x);
    }
};

struct MyTypeCompare {
  bool operator()(const MyType& o1, const MyType& o2) const {
    return o1.x == o2.x;
  }
};

std::unordered_set<MyType, MyTypeHash, MyTypeCompare> mySet;

第二种方法让我为 std::unordered_set 的每个新实例选择新的行为。 ,而第一种方法作为类型本身的一部分的行为将始终相同。

现在,如果我知道我只想要一个行为(我永远不会为 MyType 定义两个不同的比较器),那么首选哪种方法?这两者之间还有哪些不同之处?

最佳答案

将行为附加到类型允许类似的代码

template<template<class> Set,class T>
auto organizeWithSet(…);

/* elsewhere */ {
  organizeWithSet<std::unordered_set,MyType>(…);
  organizeWithSet<std::set,MyType>(…);
}

这显然不能传递自定义函数对象。

也就是说,可以定义
template<class T>
using MyUnorderedSet=std::unordered_set<T, MyTypeHash,MyTypeCompare>;

并将其用作模板模板参数,尽管它引入了另一个名称并且可能被认为不太可读。

否则,您必须考虑到您的 operator==同时是 std::unordered_set 的默认值和 std::find等;如果出于这些目的您想要的等价物有所不同,您可能需要命名比较器。另一方面,如果一个就足够了,C++20 甚至可以让你只用 =default 来定义它。 .

关于c++ - 具有覆盖运算符或外部仿函数的可散列类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075409/

相关文章:

c++ - 覆盖模板类上的赋值运算符时的奇怪行为

c++ - 如何重新专门化模板?

haskell - 仿函数泛化问题

c++ - 适用于 begin() 但不适用于 rbegin() 的映射迭代器

c++ - 复制构造函数+浅复制和深复制

c++ - 获取大的负数打印数组

c++ - PIMPL 无法在 macOS 上编译

c++ - 在 C++ 的子类中强制执行静态方法重载

c++ - 使用 STL 算法,传递函数指针或仿函数哪个更好?

haskell - 为什么 Control.Monad.Morph.hoist 有 Monad 约束?