9

STL 使用“小于”作为默认比较器。即使基础类定义了“<”运算符,对使用 reference_wrapper<> 包装的对象的 STL 比较器调用也不会编译。

看来,这是因为当LHS.operator<(RHS)是成员函数时,没有在LHS上执行隐式转换。我已经验证了使用免费版本作为比较器的工作原理。

但是,如果 reference_wrapper 提供了“<”运算符,它在底层调用“<”,则无需使用 free 函数。

我在 reference_wrapper 的代码中添加了以下内容(取自 VS11 Beta xrefwrap.h),并且可以将 std::map 与包装在我的 reference_wrapper<> 版本中的类一起使用,该版本定义了“<”运算符。

    bool operator <(reference_wrapper<_Ty> const rhs) const {
    return this->get() < rhs.get();
}

稍后添加:如果我理解正确,reference_wrapper<> 提供了与许多库所需的 ptr 相关的复制/分配语义,同时隐藏了与 ptr 相关的语法。这允许使用引用类型语法,而没有本地副本的开销。将它与使用 ptrs 的示例进行比较完全错过了 reference_wrappers 的要点之一:要避免使用 ptr 类型语法。

现在的情况是,直接作用于对象的代码在对象被包装在 reference_wrappers 中时会中断。不用说,“<”是默认的比较器,确实使它特别;在现有代码的很大一部分中,对象将定义这些以消除对特殊比较器的需要。

稍后添加 #2:此功能的历史表明,避免使用 ptr 语法并不是最初的意图。然而,自从它首次在 boost 中引入以来已经有十年了。随着大量新程序员“指导”避免使用基于 ptr 的语法(无疑受到 ptr 自由语言的影响),如果它可以更无缝地工作,特别是在处理在 STL 容器中存储对象的遗留代码时,此功能将变得越来越有用,并且价值复制遍地。

稍后添加 #3:以最少的代码更改改进遗留代码 随着时间的推移,瘦类变得繁重,容器中对象的大小增加。提高性能的一种快速方法是通过包装对象避免复制。这将提供“C ptr”类型的性能,而无需对代码进行最小更改的额外副本。

std::map<const Object, string> objTable;
// can be rewritten as to avoid object copies using the
// __myOwn::reference_wrapper which contains the '<' operator
std::map<__myOwn::reference_wrapper<const Object>, string> rwTable_myOwn;

// which works with out any non-member free comparator functions
rwTable_myOwn[a]="One"; // Compiles and works

// When using the table with the std::reference_wrapper
std::map<std::reference_wrapper<const Object>, string> rwTable_std;
//the map does not work
rwTable_std[a]="One"; // Fails to compile it needs the custom non-member comparator
4

1 回答 1

9

不,不应该。除了将引用包装为值之外,它reference_wrapper不做任何事情。

如果您需要比较两个reference_wrapper<T>(这不是对 的引用T),那么您的工作就是完成这项工作。出于同样的原因std::set<T*>,默认情况下不会将比较定义为std::less<T>(*x, *y),您的情况也不应如此。包装器只是一个非空指针。

为什么要停在单个比较运算符或所有比较运算符上?为什么不为所有标准函数重载引用包装器?因为当解决方案如此简单时,它不值得。

于 2012-05-24T02:34:48.780 回答