【问题标题】:std::find fails on a std::vector<std::reference_wrapper<T>> with a "no match for ‘operator==’" error when T is in a namespace当 T 在命名空间中时,std::find 在 std::vector<std::reference_wrapper<T>> 上失败,并出现“与‘operator==’不匹配”错误
【发布时间】:2020-01-30 16:47:49
【问题描述】:

我目前正在处理一个大型代码项目,并希望借此机会了解和使用命名空间。我定义的所有类都位于一个命名空间 Test 中。

我的一个类(此处称为 Thing)具有唯一 ID。我需要能够保存对某些事物的引用的 std::vector,因此我正在使用 std::reference_wrappers。在程序中,我需要从向量中删除某些 std::reference_wrappers,所以我使用 std::find:

#include <algorithm>
#include <functional>
#include <vector>

namespace Test {

class Thing {
private:
    const int id;

public:
    Thing(int id);
    const int ID() const;
};

}

Test::Thing::Thing(int id) : id(id) { }

const int Test::Thing::ID() const {
    return id;
}

inline bool operator==(const Test::Thing& lhs, const Test::Thing& rhs) {
    return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Test::Thing& lhs, const Test::Thing& rhs) {
    return !(lhs == rhs);
}

int main() {
    Test::Thing t1(5);
    Test::Thing t2(7);

    auto ref1 = std::ref(t1);
    auto ref2 = std::ref(t2);

    std::vector<std::reference_wrapper<Test::Thing>> v;
    v.push_back(ref1);
    v.push_back(ref2);

    auto pos = std::find(v.begin(), v.end(), ref2);
}

当我尝试编译它时,我得到一个错误:

error: no match for ‘operator==’ (operand types are ‘std::reference_wrapper<Test::Thing>’ and ‘const std::reference_wrapper<Test::Thing>’)

但是,如果我删除命名空间,代码会正确编译:

#include <functional>
#include <vector>
#include <algorithm>

class Thing {
private:
    const int id;

public:
    Thing(int id);
    const int ID() const;
};

Thing::Thing(int id) : id(id) { }

const int Thing::ID() const {
    return id;
}

inline bool operator==(const Thing& lhs, const Thing& rhs) {
    return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Thing& lhs, const Thing& rhs) {
    return !(lhs == rhs);
}

int main() {
    Thing t1(5);
    Thing t2(7);

    auto ref1 = std::ref(t1);
    auto ref2 = std::ref(t2);

    std::vector<std::reference_wrapper<Thing>> v;
    v.push_back(ref1);
    v.push_back(ref2);

    auto pos = std::find(v.begin(), v.end(), ref2);
}

【问题讨论】:

    标签: c++ vector namespaces reference-wrapper


    【解决方案1】:

    正确的解决方案是将运算符移动到Argument-dependent lookup (ADL) 可以找到它们的命名空间:

    namespace Test {
    
    class Thing {
    private:
        const int id;
    
    public:
        Thing(int id);
        const int ID() const;
    };
    
    
    inline bool operator==(const Thing& lhs, const Thing& rhs) {
        return lhs.ID() == rhs.ID();
    }
    inline bool operator!=(const Thing& lhs, const Thing& rhs) {
        return !(lhs == rhs);
    }
    
    }
    
    Test::Thing::Thing(int id) : id(id) { }
    
    const int Test::Thing::ID() const {
        return id;
    }
    

    [Live example]

    标准库已经使用 &lt;&lt; 等运算符进行流插入。

    【讨论】:

    • 我是否正确理解这一点,为了使用operator== 中内置的类,std::reference_wrapper 需要对其进行扩展?
    猜你喜欢
    • 2023-02-16
    • 2016-03-31
    • 1970-01-01
    • 2017-09-01
    • 2015-10-11
    • 2016-01-23
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多