简体   繁体   English

为什么我的模板运算符==不被使用?

[英]Why does my templated operator== not get used?

I have defined operator== as follows: 我已经定义了operator== ,如下所示:

template <class State>
bool operator==(const std::shared_ptr<const State> &lhs,
                const std::shared_ptr<const State> &rhs) {
    return *lhs == *rhs;
}

This operator does not get instantiated (in gdb , I cannot set the break-point on the return statement -- the line does not exist). 此运算符不会实例化(在gdb ,我无法在return语句上设置断点-该行不存在)。

However, this operator should be used by std::find called in this line: 但是,此操作符应由以下行中调用的std::find使用:

return std::find(v.begin(), v.end(), el) != v.end();

I checked the type of v in the above line in gdb : 我在gdb的上一行中检查了v的类型:

(gdb) whatis v
type = const std::vector<std::shared_ptr<Domains::IncWorst const>> &
(gdb) whatis el
type = const std::shared_ptr<Domains::IncWorst const> &

Doesn't this match my templated operator== with State being IncWorst ? 这不匹配我的模板operator==StateIncWorst吗?

I implemented a toy example as follows and the example works, so I cannot understand why the real code does not. 我实现了一个玩具示例,并且该示例可以正常工作,因此我无法理解为什么真正的代码不起作用。

template<class V, typename T>
bool in(const V &v, const T &el) {
    return std::find(v.begin(), v.end(), el) != v.end();
}

struct MyState {
    MyState(int xx) : x(xx) {}
    bool operator==(const MyState &rhs) const {
        return x == rhs.x;
    }
    int x;
};

template <class State>
bool operator==(const std::shared_ptr<const State> &lhs,
                const std::shared_ptr<const State> &rhs) {
    return *lhs == *rhs;
}

int main() {
    std::vector<std::shared_ptr<const MyState>> v{
        std::make_shared<const MyState>(5)};
    auto p = std::make_shared<const MyState>(5);
    std::cout << in(v, p) << std::endl; // outputs 1
    return 0;
}

Your operator== template is in the wrong namespace. 您的operator==模板位于错误的名称空间中。

In order to be found by ADL, it must be either in the std namespace (which would be illegal, per [ namespace.std ]/1 ) or in Domains (per [basic.lookup.argdep] /2 ). 为了被ADL查找,它必须位于std命名空间中(根据[[ namespace.std ] / 1 ,这是非法的)或在Domains (根据[basic.lookup.argdep] / 2 )。

However, this is still highly dangerous, since if any template performing an equality comparison (eg but not limited to std::find ) is instantiated both before and after your operator== template is declared, your whole program will be invalid per [temp.point] /8 and [basic.def.odr] /6 . 但是,这仍然是非常危险的,因为如果在声明operator==模板之前和之后都实例化了执行相等比较的模板(例如但不限于std::find ),则每个[temp .point] / 8[basic.def.odr] / 6

If you must provide operator overload templates for std::shared_ptr s of your types, prefer to explicitly instantiate them after the declaration of each class, such that there is less chance of a template being instantiated somewhere the class is not visible: 如果必须为您的类型的std::shared_ptr提供运算符重载模板,则最好在每个类的声明之后显式实例化它们,这样可以减少在类不可见的地方实例化模板的机会:

struct MyState {
    // ...
};
template bool operator==<MyState>(
    const std::shared_ptr<MyState const>&,
    const std::shared_ptr<MyState const>&);

This could still be problematic if someone forward-declares MyState somewhere else, but it's probably the best you can do. 如果有人在其他地方转发声明MyState ,这仍然可能会出现问题,但这可能是您可以做的最好的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM