为什么标准容器使用函数模板而不是非模板Koenig操作符
Why standard containers use function templates instead of non-template Koenig operators
这个问题的灵感来自Issue with std::reference_wrapper。比如说,用operator<
代替std::vector
。它被定义为函数模板
template< class T, class Alloc >
bool operator<( const vector<T,Alloc>& lhs,
const vector<T,Alloc>& rhs );
因此,拒绝将函数实参隐式转换为相应函数形参的类型(主要是因为它的模板性质)。这大大降低了std::reference_wrapper
的实用性和方便性。例如,不能在std::vector<std::reference_wrapper<std::vector<int>>>
上使用std::sort
。
operator<
定义为像
这样的非模板Koenig操作符,才能解决所有问题。template <...>
class vector ... {
friend bool operator<(const vector& a, const vector& b) {...}
};
我想知道为什么标准库采用了前一种方法而不是这种方法?
考虑以下代码:
template <class T>
class A {
public:
T m_x;
friend bool operator<(const A & lhs, const A & rhs) {
return lhs.m_x < rhs.m_x;
}
};
和main.cpp:
#include "A.h"
namespace buddy {
bool operator<(const A<double> & lhs, const A<double> &rhs) {
return lhs.m_x > rhs.m_x;
};
}
using namespace buddy;
int main(int argc, char ** argv) {
A<double> a1;
A<double> a2;
a1 < a2;
return 0;
}
这段代码不能编译:
main.cpp:14:5: error: ambiguous overload for ' operator<'(操作数类型为' A '和' A ')a1 & lt;a2;
原因当然是两个操作符<s都是精确匹配的。另一方面,如果我们改变第一个操作符><To(在类之外定义):>template <class T>
bool operator<(const A<T> & lhs, const A<T> & rhs) {
return lhs.m_x < rhs.m_x;
}
编译器不再抱怨:现在是精确匹配和函数模板之间的竞争,所以使用了精确匹配。
如果operator<如果按照你所建议的方式定义,std::vector的用户将没有合理的方法来重新定义operator><的行为,除非对std::vector本身进行专门化,这需要做更多的工作。>
总之,标准编写者选择使重载operator<比提供operator><这在某些情况下可能更有用。我认为他们的选择是正确的。>比提供operator>
相关文章:
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 为什么 std::optional::operator=(U&&) 要求你是非标量类型?
- 是否可以在C++中有一个"generic"模板参数,该参数可以是非类型模板参数或类型?
- NVCC 错误:string_view.h:constexpr 函数返回是非常量
- 编译器是否必须始终删除 try-catch 块(如果它被证明是非抛出的)
- C++ 电话号码字母拨号程序 - 语法错别字?还是非 ASCII 字符?
- 什么是非营利组织???我的问题是我不明白为什么有人会使用它
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- 错误:请求成员 .. 是非类类型"char"
- 具有定义模板还是非模板的友元函数
- 为什么map有操作符[],set没有
- 为什么在C++中,内建赋值返回的是非常量引用而不是常量引用
- 请求成员 'begin' in 'c' 中,它是非类类型 'char [101]' sort(c.begin(), c
- 为什么类的赋值运算符的返回类型通常是非常量(而不是常量)引用?
- 什么是非时态流式处理负载内部 (_mm256_stream_load_si256) 的浮点 (__m256d) 版本?
- 枚举不是非静态数据成员或类的基类
- 基类中的虚拟方法和子类中的非 Virtula 方法.仍然如何调用子类方法,即使它是非虚拟的
- 请求成员“写入”中的“chol_out_data”,这是非类类型
- 为什么标准容器使用函数模板而不是非模板Koenig操作符
- 为什么重载复合赋值操作符可以是非成员函数