当我尝试使用这样的代码时:
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')
(指向&lt; 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() );
}
然后编译。我可以这样做,但我想知道为什么第一次尝试失败了。
在解决方案之后添加: Namespaces & Interface Principle由Herb Sutter帮助我更多地澄清这些内容。
答案 0 :(得分:4)
operator<
无法找到lower_bound
,因为它不在与您使用的类型相关联的任何名称空间中。
编译器将查找名称空间std
和boost
,但不会查找全局名称空间,因为没有涉及的内容。
当你传递Comp
explicilty时,它有效,因为编译器不必搜索匹配的运算符。
答案 1 :(得分:3)
对operator <
的调用是在std
命名空间内执行的。因此,编译器将在operator <
命名空间和其参数的命名空间(ADL)中查找std
的适当重载。如果找到一个运算符(即使它不可行!),则封闭名称空间不搜索。
由于在全局命名空间中定义了operator <
,编译器不会考虑它(因为operator <
命名空间中存在另一个重载std
,并且在名称查找之前可以考虑封闭命名空间)。
最后,由于std::operator <
不可行,编译器将发出错误。
当你将自己的仿函数作为最后一个参数传递时,事情显然是不同的:不是寻找可行的operator <
,而是调用参数本身,并且一切都编译得很好。