带有重载运算符的自定义类用作映射键时会导致C2678 [英] Custom class with overloaded operators causes C2678 when used as map key

查看:111
本文介绍了带有重载运算符的自定义类用作映射键时会导致C2678的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我这里有些奇怪.

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

I have written a custom class 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;

在地图中将其用作上述键时,出现以下错误:

When using it in a map as a key like above i get the following error:

二元运算符'<' :没有定义运算符,该运算符采用'const HashedString'类型的左操作数(或者没有可接受的转换)

binary operator '<' : no operator defined which takes a left-hand operand of type 'const HashedString' (or there is no acceptable conversion)

我无法使其正常运行,而且我不理解为什么编译器会拒绝此代码.

I am not able to get it work, furthermore i don't understand why this code is rejected by the compiler.

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

Does anybody know the solution and the mistake i have done here?

感谢Xeno

推荐答案

您需要将运算符设置为const.还应该使用const引用:

You need to make your operator const. It should also take a const reference:

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

或者,您可以将其设为非会员运算符:

Alternatively, you can make it a non-menber operator:

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

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

This would be the preferred option, since it is symmetrical for both operands.

请注意,比较运算符将其任何一个操作数进行突变都没有意义.这适用于所有比较运算符.

Note that it doesn't make sense for a comparison operator to mutate either of its operands. This applies to all of your comparison operators.

最后,要使其正常工作,您还必须制作GetHash() const:

Finally, for this to work, you will have to make GetHash() const too:

long GetHash() const;

编辑:我以前没有讨论过,但是很明显,这种机制对于散列冲突是脆弱的.除非您在键值范围内具有完美的哈希,否则最好使用std::unordered_map<std::string>.

Edit: I didn't go into this before, but clearly this mechanism is fragile against hash collisions. Unless you have perfect hashing in your range of key values, you may be better off using an std::unordered_map<std::string>.

这篇关于带有重载运算符的自定义类用作映射键时会导致C2678的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆