JWWalker
JWWalker

Reputation: 22717

Error with operator< overload, invalid operands

When I try to use code like this:

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

I get an error:

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

(with a pointer to the < comparison in the implementation of lower_bound.) So, why are they invalid, when I provided an operator< with those operands?

If I instead use a comparison functor,

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

then it compiles. I could just do things that way, but I'd like to know why the first attempt failed.

Added after solution: Namespaces & Interface Principle by Herb Sutter helped clarify this stuff for me more.

Upvotes: 0

Views: 793

Answers (2)

Andy Prowl
Andy Prowl

Reputation: 126562

The call to operator < is performed inside the std namespace. The compiler will therefore look for appropriate overloads of operator < in the std namespace and in the namespace of its arguments (ADL). If one operator is found (even if it is not viable!), enclosing namespaces are not searched.

Since your operator < is defined in the global namespace, the compiler will not consider it (since another overload operator < exists in the std namespace and is found before name look up may consider enclosing namespaces).

Finally, since std::operator < is not viable, the compiler will emit an error.

When passing your own functor as the last argument, things are obviously different: instead of looking for a viable operator <, the argument itself is invoked, and everything compiles fine.

Upvotes: 4

Bo Persson
Bo Persson

Reputation: 92381

Your operator< will not be found by lower_bound, because it is not in any namespace associated with the types you use.

The compiler will look in namespaces std and boost, but not in the global namespace because nothing involved comes from there.

When you pass Comp explicilty it works, because then the compiler doesn't have to search for a matching operator.

Upvotes: 4

Related Questions