作为模板参数的 C++ 方法

标签 c++ templates

我正在尝试将 std::unordered_map 专门化为具有自定义散列和自定义相等性的类 X。问题是相等函数和哈希函数不仅依赖于类 X 的对象,还依赖于另一个类 Y 的另一个(固定)对象中的数据。这是一个玩具示例(仅具有哈希函数)我想做的事情:

#include <unordered_map>
using namespace std;
struct Y {
  bool b;
  struct X {
    size_t i;
  };
  size_t hash(const X &x) {
    return x.i + b;
  }
  unordered_map<X, int, hash> mymap;
};

问题是模板特化中的函数散列是一个方法,编译器会提示(“调用没有对象参数的非静态成员函数”)。我想要的是 y.mymap 使用 y.hash()。有什么办法吗?

请注意,在实际代码中,Y 也是一个模板,以防万一。

谢谢!

编辑:为了澄清,我的代码中没有 bool 值 b,而是有一个 vector ,其中包含比较 X 类型对象所需的数据。创建 X 时会添加一些数据,因此 vector 不是常量,但是给定 X 的数据在添加后不会改变,因此给定 X 的散列永远不会改变(因此在某种意义上它仅取决于散列所需的 X)。我使用这种方法的主要原因是为了节省内存,因为这些数据很多而且通常是共享的。

最佳答案

您可以使用 function<size_t(X const&)>和例如bind , 但由于在这种情况下不需要类型删除,这里有一个更简单的解决方案:

struct Y {
    bool b;
    struct X {
        size_t i;
        bool operator==(X x) const {return i == x.i;}
    };
    size_t hash(const X &x) {
      return x.i + b;
    }

    struct Hasher {
        Y* this_;
        template <typename T>
        auto operator()(T&& t) const
          -> decltype(this_->hash(std::forward<T>(t))) {
            return    this_->hash(std::forward<T>(t));
        }
    };

    unordered_map<X, int, Hasher> mymap;

    Y() : b(false),
          mymap(0, {this}) {}
};

正如@dyp 在评论中提到的,您必须小心特殊的成员函数,因为我们隐式存储了 this。在 mymap - 即编译器生成的定义将复制 this_指针。移动构造函数的示例实现可以是

Y(Y&& y) : b(y.b), mymap(std::make_move_iterator(std::begin(y.mymap)),
                         std::make_move_iterator(std::end  (y.mymap)), 0, {this}) {}

关于作为模板参数的 C++ 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29632309/

相关文章:

c++ - 检查整数常量在编译时有不同的值

c++ - 我可以使用 "using"而不是 "typedef"作为指向类成员变量的指针吗?

c++ - 在 Cocos2d-x 中同步函数?

c++ - 如何最好地从模板困惑切换到干净的类架构 (C++)?

c++ - 如何同时别名和实例化模板函数?

c# - C++ Vector 类似于 C# 中的类

c++ - 结构的原型(prototype)函数

c++ - 使用仿函数的返回类型来声明模板方法的返回类型,而不使用 decltype

c++ - 我已经创建了一个模板函数,但在检查输入是奇数还是偶数时出现错误 C++

c++ - std::begin 的 SFINAE 问题