关于运算符重载的澄清

问题描述 投票:0回答:1

为了提供上下文,我有一个可执行文件,它依赖于另一个提供 Identifier 类实现的 Foo 库,现在我的可执行文件中的模块类需要缓存以 Identifier 为键的 Foo 对象,所以我添加了如下所示的逻辑

class Module {
public:
    
    static std::shared_ptr<Module> create();

    explicit Module() = default;

    ...
protected:
    ...
    /// Map that caches Foo object keyed on @c Identifier.
    std::map<Identifier,Foo> m_FooMap;
};

在我的 Module.cpp 中,我将如下插入到地图中

Foo foo; m_FooMap.emplace(identifier, foo);
但是当我尝试编译时出现以下错误

/local/home/workspace/build/usr/include/c++/v1/__functional/operations.h:372:21: error: invalid operands to binary expression ('const Identifier' and 'const Identifier')
        {return __x < __y;}
                ~~~ ^ ~~~
/local/home/workspace/build/usr/include/c++/v1/map:598:17: note: in instantiation of member function 'std::less<Identifier>::operator()' requested here
        {return static_cast<const _Compare&>(*this)(__x, __y.__get_value().first);}
                ^
/local/home/workspace/build/usr/include/c++/v1/__tree:1974:17: note: in instantiation of member function 'std::__map_value_compare<Identifier, Foo>, std::less<Identifier>, true>::operator()' requested here
            if (value_comp()(__v, __nd->__value_))
                ^

根据我的理解,Identifier 类似乎缺少小于运算符,并且由于我无法对提供 Identifier 实现的 Foo 库进行更改,因此我尝试在 Module.h 文件中为 Identifier 重载小于和等于运算符本身

// Overloading the less-than operator for the Identifier
// objects
bool operator<(const Identifier& lhs, const Identifier& rhs){
    return (lhs.field1 < rhs.field1);
}

// Overloading the equal to operator for the Identifier
// objects
bool operator==(const Identifier& lhs, const Identifier& rhs){
    return (lhs.field1 == rhs.field1);
}

但我仍然看到同样的错误。因此想澄清我的理解是否正确,即标识符类缺少小于运算符重载,一旦提供,我们就可以根据标识符进行键入。另外,由于我无法修改提供 Identifier 类的 Foo 库中的逻辑,我可以提供自己的 Identifier 类的自定义运算符重载(如上所示),还是不可行,如果可行,还有什么替代方案。

c++ c++11 operator-overloading
1个回答
0
投票

至少在我读到的内容中,你目前的情况差不多是这样的:

#include <string>
#include <map>

// defined in some other file, but class definition included via a header:
namespace library { 
    class Identifier {
    public:
        Identifier(std::string const &s) : data(s) {}

        explicit operator std::string() const { return data; }
        std::string data;
    };
}

bool operator<(library::Identifier const &a, library::Identifier const &b) { 
    return a.data < b.data;
}

class Foo {
    std::map<library::Identifier, int> data;
public:
    void insert(library::Identifier const &s, int i) { 
        data[s] = i;
    }
};

int main() { 

    Foo f;
    library::Identifier i("foo");

    f.insert(i, 1);
}

你有一些库定义的

Identifier
。在您自己的班级中,您有一个
map
试图使用
Identifier
作为键。由于
Identifier
本身并没有定义
operator<
,因此您自己定义了一个。但仍然没有找到,编译仍然失败,就像你根本没有定义
operator<
一样。

我在命名空间内定义了

Identifier
,因为我相当确定您的代码中就是这种情况。更重要的是,它位于命名空间中是编译器找不到并且不会使用您定义的运算符的真正原因。

幸运的是,解决这个问题相当容易。您需要将运算符放在与

Identifier
本身定义相同的命名空间中:

#include <string>
#include <map>

// defined in some other file, but class definition included via a header:
namespace library { 
    class Identifier {
    public:
        Identifier(std::string const &s) : data(s) {}

        explicit operator std::string() const { return data; }
        std::string data;
    };
}

// The only change we've made is here, putting the `operator<` into
// the same namespace as the class of operands it takes as operands:
namespace library {
bool operator<(library::Identifier const &a, library::Identifier const &b) { 
    return a.data < b.data;
}
}

class Foo {
    std::map<library::Identifier, int> data;
public:
    void insert(library::Identifier const &s, int i) { 
        data[s] = i;
    }
};

int main() { 

    Foo f;
    library::Identifier i("foo");

    f.insert(i, 1);
}

这样,代码就可以正常编译了。

© www.soinside.com 2019 - 2024. All rights reserved.