c ++方法作为模板参数

时间:2015-04-14 16:11:40

标签: c++ templates

我正在尝试使用自定义哈希和自定义相等来为类X专门化std :: unordered_map。问题是,相等和散列函数不仅依赖于类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也是一个模板,以防万一。

谢谢!

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

2 个答案:

答案 0 :(得分:2)

不幸的是,你想做的事情是不合法的。见17.6.3.5/Table 26:

  

h(k)返回的值仅取决于参数k。

很明显,您不允许哈希取决于Y以及X的成员。

编辑:以防万一{/ 1}} b成为你的Y类中的const有一个解决方案(我还没有编译它,如果有机会的话我会的):< / p>

struct Y
{
    explicit Y(bool config) : b(config), hash_(config), mymap(0, hash_) { }
    const bool b;

    struct X
    {
        size_t i;
    };

    struct Hash
    {
        explicit Hash(bool b) : b_(b) { }
        size_t operator()(const X& x) const
        {
            return x.i + b_;
        }

    private:
        bool b_;
    };

    Hash hash_;
    unordered_map<X, int, Hash> mymap;
};

答案 1 :(得分:2)

您可以使用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}) {}