std :: reference_wrapper是否应包含默认比较器“<”运营商?

时间:2012-05-24 01:44:46

标签: c++ stl c++11 reference-wrapper

STL使用“小于”作为默认比较器。 STL比较器调用用reference_wrapper<>包裹的对象。 does not compile,即使基础类具有“<”运营商定义。

看来,这是因为当它是一个成员函数时, LHS.operator<(RHS) LHS 上执行了no implicit conversion 。我已经验证了using a free version作为比较器的工作原理。

但是,如果reference_wrapper提供了“<”运算符,调用“<”在底层,将使用免费功能的需要将被避免。

我在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&lt;&gt;提供与许多库所需的ptrs相关联的复制/分配语义,同时隐藏与ptr相关的语法。这允许使用引用类型语法,而不需要本地副本的开销。要将它与使用ptrs的示例进行比较,完全错过了reference_wrappers的 一个 您希望避免使用ptr类型语法。 < / p>

现在的情况就是,当对象被包装在reference_wrappers中时,直接处理对象的代码会中断。不用说,“&lt;”作为默认比较器,确实使它变得特别;在很大比例的现有代码中,对象将定义这些代码以避免需要特殊的比较器。

后来添加#2: 此功能的历史表明,避免使用ptr语法并不是最初的意图。然而,自推出首次推出以来已经过去了十年。由于大量新程序员“被引导”to avoid ptr based syntax(毫无疑问受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

1 个答案:

答案 0 :(得分:9)

不,不应该。执行任何操作都不是reference_wrapper的工作,而是将引用包装为值。

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

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