0

当我尝试使用这样的代码时:

namespace
{
    typedef boost::shared_ptr< float >  sharedFloat;
}

static bool operator<( const sharedFloat& inOne, float inTwo )
{
    return *inOne < inTwo;
}

static void foo()
{
    std::vector< sharedFloat > theVec;
    std::vector< sharedFloat >::iterator i =
        std::lower_bound( theVec.begin(), theVec.end(), 3.4f );
}

我收到一个错误:

error: invalid operands to binary expression ('boost::shared_ptr<float>' and 'float')

(在 的实现中有一个指向 < 比较的指针lower_bound。)那么,当我提供这些操作数时,为什么它们无效operator<

如果我改为使用比较函子,

namespace
{
    typedef boost::shared_ptr< float >  sharedFloat;

    struct Comp
    {
        bool operator()( const sharedFloat& inOne, float inTwo )
        {
            return *inOne < inTwo;
        }
    };
}

static void foo()
{
    std::vector< sharedFloat > theVec;
    std::vector< sharedFloat >::iterator i =
        std::lower_bound( theVec.begin(), theVec.end(), 3.4f, Comp() );
}

然后它编译。我可以那样做,但我想知道为什么第一次尝试失败了。

解决方案后添加: Herb Sutter 的 Namespaces & Interface Principle帮助我更清楚地了解了这些内容。

4

2 回答 2

4

operator<将不会被 找到lower_bound,因为它不在与您使用的类型关联的任何命名空间中。

编译器将在命名空间std和中查找boost,但不会在全局命名空间中查找,因为那里没有涉及任何内容。

当您通过Comp显式时,它会起作用,因为编译器不必搜索匹配的运算符。

于 2013-03-12T21:31:50.500 回答
3

调用operator <在命名空间内执行stdoperator <因此,编译器将在std命名空间及其参数 (ADL) 的命名空间中寻找适当的重载。如果找到一个运算符(即使它不可行!),则不会搜索封闭的命名空间。

由于您operator <是在全局命名空间中定义的,因此编译器不会考虑它(因为命名空间operator <中存在另一个重载std并且在名称查找之前发现可能会考虑封闭命名空间)。

最后,由于std::operator <不可行,编译器会发出错误。

当将您自己的仿函数作为最后一个参数传递时,情况显然有所不同:不是寻找可行operator <的,而是调用参数本身,并且一切都可以正常编译。

于 2013-03-12T21:24:13.780 回答