Custom class with overloaded operators causes C2678 when used as map key

北城以北 提交于 2019-12-25 15:29:26

问题


i've got something strange here.

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:

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?

Thanks, Xeno


回答1:


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.

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

long GetHash() const;

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>.



来源:https://stackoverflow.com/questions/21123472/custom-class-with-overloaded-operators-causes-c2678-when-used-as-map-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!