考虑这个问题,它是关于以下代码无法编译的:
std::vector<int> a, b;
std::cout << (std::ref(a) < std::ref(b));
不能编译,因为vector
的vector比较操作符是非成员函数模板,并且不允许考虑隐式转换。但是,如果将操作符写成非成员非模板,则friend
函数:
template <class T, class Allocator = std::allocator<T>>
class vector {
// ...
friend bool operator<(const vector& lhs, const vector& rhs) {
// impl details
}
};
则该版本的operator<
将被ADL发现并选择为最佳可行过载,并编译原始示例。考虑到这一点,是否有理由更喜欢我们目前拥有的非成员函数模板,或者这应该被认为是标准中的缺陷?
既然如此,是否有理由选择非成员函数模板,或者这应该被认为是一个缺陷在标准中?
原因在于ADL能否找到合适的功能。当这样的搜索需要从给定对象的类型中提取被替换的模板参数,然后将它们多次替换为函数模板的模板化参数时,ADL不能这样做,因为在一般情况下没有理由选择一种模板参数绑定到另一种方式。在该模板之后定义但仍在该模板的命名空间范围内的非成员函数模板(由于friend
)排除了这种不确定性。