为什么我的模板化运算符==没有被使用?

时间:2016-07-28 14:10:26

标签: c++ templates operator-overloading

我已将operator==定义如下:

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

此运算符未实例化(在gdb中,我无法在return语句中设置断点 - 该行不存在)。

但是,此行中的std::find应使用此运算符:

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

我在v中检查了上一行中gdb的类型:

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

这与我的模板operator==匹配,而StateIncWorst吗?

我实现了一个玩具示例如下,示例有效,所以我无法理解为什么真正的代码没有。

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;
}

1 个答案:

答案 0 :(得分:3)

您的operator==模板位于错误的命名空间中。

为了能够被ADL找到,它必须位于std命名空间(这可能是非法的,每[namespace.std]/1个)或Domains(每[basic.lookup.argdep]/2} )。

但是,这仍然非常危险,因为如果在声明std::find模板之前和之后实例化任何执行相等比较的模板(例如但不限于operator==),那么整个程序将根据[temp.point]/8[basic.def.odr]/6无效。

如果必须为类型的std::shared_ptr提供运算符重载模板,则更喜欢在声明每个类之后显式实例化它们,这样模板的可能性就会降低在某个地方实例化该类是不可见的:

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

如果有人在其他地方向前宣布MyState,这可能仍会有问题,但这可能是你能做到的最好的事情。