Reputation: 22717
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
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
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