【问题标题】:Why standard containers use function templates instead of non-template Koenig operators为什么标准容器使用函数模板而不是非模板 Koenig 运算符
【发布时间】:2015-05-15 17:39:48
【问题描述】:

这个问题的灵感来自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&lt;std::reference_wrapper&lt;std::vector&lt;int&gt;&gt;&gt; 上使用 std::sort

另一方面,只有将operator&lt; 定义为像这样的非模板 Koenig 运算符,才能解决所有问题

template <...>
class vector ... {
  friend bool operator<(const vector& a, const vector& b) {...}
};

我想知道为什么标准库采用了前一种方法而不是这种方法?

【问题讨论】:

  • 好吧,在 operator &lt; 标准化的时候,reference_wrapper 不存在,AFAIK。
  • 关于措辞:没有 Koenig 运算符。相反,有一些函数可以通过 ADL/Koenig 查找找到。
  • 这不是问题,但我认为在发明 SGI STL 的时候,它仍然与优化器相关。 -- 还要注意这个函数不需要是朋友(不需要特权访问),所以也许它被认为是一个更干净的解决方案。
  • 也许更好的方式来允许这个 btw 是添加包装操作符到std::reference_wrapper,就像它的operator()一样。
  • 这里有一个问题:假设您想为 std::vector 重载 operator

标签: c++ c++11 implicit-conversion standard-library reference-wrapper


【解决方案1】:

考虑以下代码 (A.h):

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: 错误:‘operator

原因当然是两个运算符

template <class T>
bool operator<(const A<T> & lhs, const A<T> & rhs) {
  return lhs.m_x < rhs.m_x;
}

编译器停止抱怨:现在是完全匹配和函数模板之间的竞争,所以使用完全匹配。

如果 operator

总之,标准编写者选择使重载 operator

【讨论】:

  • "std::vector 的用户没有合理的方法来重新定义运算符的行为 您似乎暗示这是一件好事。我不认为我会同意。例如,标准库中的通用算法允许传递比较器函数对象,以指定自定义顺序关系。
  • 对于向量而言,运算符
  • Alexander Stepanov,SGI STL 的发明者之一,肯定会不同意:operator&lt;operator==(以及它们的严格弱排序和相等的特定语义)是创建类型所必需的常规。例如,operator&lt; 是排序和快速查找(二分查找)所必需的。所以,我不认为这个重新定义operator&lt;的“漏洞”是故意引入的。
  • 我的意思是,这个特定的操作符没有任何基本原理
  • "Unordered_map/set 没有运算符 我怀疑:所需属性之一是 [@987654328 @ 等价于a == b]。由于集合是无序的,我想这样的operator&lt; 无法有效实现(例如,两个相等的映射/集合具有不同的桶数)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
  • 1970-01-01
  • 2011-09-28
  • 2020-09-04
  • 2013-12-08
  • 2013-01-17
相关资源
最近更新 更多