具有重载运算符的自定义类在用作映射键时会导致C2678

时间:2014-01-14 20:35:53

标签: c++ visual-studio-2012 c++11 compiler-errors operators

我在这里有点奇怪。

我编写了一个自定义类HashedString:

class HashedString {
        protected:
            std::string str;
            long hash;

        public:
            HashedString(std::string str);
            ~HashedString();

            std::string GetString();
            long GetHash();

            bool operator== ( HashedString & o ) {
                return this->hash == o.GetHash();
            }
            bool operator<= ( HashedString & o ) {
                return this->hash <= o.GetHash();
            }
            bool operator>= ( HashedString & o ) {
                return this->hash >= o.GetHash();
            }
            bool operator< ( HashedString& o ) {
                return hash < o.GetHash();
            }
            bool operator> ( HashedString & o ) {
                return this->hash > o.GetHash();
            }
            bool operator!= ( HashedString & o ) {
                return this->hash != o.GetHash();
            }
            std::ostream& operator<<(std::ostream& lhs) {
                return lhs << "{" << hash << ": " << str << "}";
            }
    };


std::map<HashedString, Resource> resources;

在地图中使用它作为上面的键时,我收到以下错误:

二元运算符'&lt;' :没有运算符定义哪个采用'const HashedString'类型的左手操作数(或者没有可接受的转换)

我无法使其工作,而且我不明白为什么编译器会拒绝此代码。

有人知道我在这里做过的解决方案和错误吗?

谢谢,Xeno

1 个答案:

答案 0 :(得分:3)

您需要设置运营商const。它还应该采用const参考:

bool operator< (const HashedString& o ) const { .... }

或者,您可以将其设为非限定运算符:

bool operator<(const HashedString& lhs, const HashedString& rhs)
{
  lhs.GetHash() < rhs.GetHash();
}

这将是首选选项,因为它对于两个操作数都是对称的。

请注意,比较运算符改变其任一操作数是没有意义的。这适用于所有比较运算符。

最后,为了实现这一目标,您还必须GetHash() const

long GetHash() const;

编辑:我之前没有进入过这个问题,但显然这种机制对于哈希冲突很脆弱。除非您在键值范围内有完美的散列,否则最好使用std::unordered_map<std::string>