0

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.

2
  • 1
    does it work if you take the typedef out of the namespace? Commented Mar 12, 2013 at 21:23
  • @EHuhtala, no, that has no effect. Commented Mar 12, 2013 at 21:33

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Why doesn't the float argument count as being in the global namespace?
@JWWalker: float is a built-in type of the language, it is not defined in any namespace. To get convinced, try doing ::float x = 0;, you will see the compiler gives you an error.
4

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.