【问题标题】:cannot contain user defined class in hash_sethash_set 中不能包含用户定义的类
【发布时间】:2013-05-29 21:13:37
【问题描述】:

我正在实现六度 Kevin Bacon 问题并为参与者节点编写一个类。 我可以使用 set 而不是 hash_set 容器来保存用户定义的类。为什么?错误消息显示:错误 C2440: 'type cast' : 无法从 'const ActorGraphNode' 转换为 'size_t' 1> 没有可以执行此转换的用户定义转换运算符,或者无法调用该运算符....

#include <hash_set>
#include <set>
class ActorGraphNode{
    public: 
    string ActorName;
    //hash_set<ActorGraphNode> linkedActors;
    set<ActorGraphNode> linkedActors;
    ActorGraphNode(string name):ActorName(name){}
    void linkCostar(ActorGraphNode actor){
       linkedActors.insert(actor);
       actor.linkedActors.insert(*this);
    }
    bool operator<( const ActorGraphNode& a ) const
    { return ActorName < a.ActorName ? true : false;}
};

【问题讨论】:

    标签: c++ stl msdn


    【解决方案1】:

    不出所料,hash_set 要求您为您的类型实现哈希函数。

    class ActorGraphNode{
        public: 
        string ActorName;
        hash_set<ActorGraphNode> linkedActors;
        //set<ActorGraphNode> linkedActors;
        ActorGraphNode(string name):ActorName(name){}
        void linkCostar(ActorGraphNode actor){
           linkedActors.insert(actor);
           actor.linkedActors.insert(*this);
        }
        bool operator<( const ActorGraphNode& a ) const
        { return ActorName < a.ActorName;}
        bool operator ==( const ActorGraphNode& a ) const
        { return ActorName == a.ActorName;}
        operator size_t() const
        {
          return hash<string>()(ActorName);
        }
    };
    

    【讨论】:

    • 你还需要相等,operator&lt; 对于无序/散列容器是不必要的。
    • Equality 可以由编译器生成,但可以肯定的是,如果您不想承担比较整个linkedActors 集的开销,您可以自己编写。
    • 我认为最好为 std::hash 制作自己的专业而不是制作 operator size_t
    • Evgeny,你能给我举个例子来说明如何编写 hash 吗?我的原始代码无法编译,因为缺少 operator size_t 这就是我添加它的原因。
    • @riv, operator== 不是编译器生成的。参见第 12 节第 1 段:“默认构造函数 (12.1)、复制构造函数和复制赋值运算符 (12.8)、移动构造函数和移动赋值运算符 (12.8) 和析构函数 (12.4) 是特殊的成员函数。[注:实现当程序未显式声明它们时,将为某些类类型隐式声明这些成员函数。如果它们被 odr-used (3.2),则实现将隐式定义它们。参见 12.1、12.4 和 12.8。-结束注释]程序不应定义隐式声明的特殊成员函数。”
    【解决方案2】:

    感谢大家的回答和 cmets。这是我在您的帮助下更新的代码。加上函数 linkCostar() 我现在使用传递引用:

    class ActorGraphNode{
    public: 
        string ActorName;
        hash_set<ActorGraphNode> linkedActors;
        ActorGraphNode(string name):ActorName(name){}
        void linkCostar(ActorGraphNode& actor){
            linkedActors.insert(actor);
            actor.linkedActors.insert(*this);
        }
        bool operator==( const ActorGraphNode& a ) const
        { return ActorName == a.ActorName ? true : false;}
        operator size_t() const
        {
            const int HASHSIZE = 501;
            int seed = 131;
            size_t sum = 0;
            for(size_t i = 0; i < ActorName.length(); ++i) 
                sum = (sum * seed) + ActorName[i];      
            return sum % HASHSIZE;
        }
    };
    

    【讨论】:

    • STL 有一个字符串的哈希函数,所以你不必自己写;如果你这样做,不要返回结果模 HASHSIZE,你基本上是通过强制你的值到 0..500 范围来增加碰撞次数。
    • thx riv,这是我对 operator size_t 的更新: operator size_t() const { hash H;返回 H(演员名); }
    猜你喜欢
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    相关资源
    最近更新 更多