当前位置: 首页 > 知识库问答 >
问题:

什么是透明比较器?

寇坚成
2023-03-14

在C 14中,关联容器似乎从C 11-[associative.reqmts]/13改为:

成员函数模板查找计数下限上限相等范围不得参与重载解析,除非类型比较::是透明的

让一个比较国“透明”的目的是什么?

C 14还提供如下库模板:

template <class T = void> struct less {
    constexpr bool operator()(const T& x, const T& y) const;
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
};

template <> struct less<void> {
    template <class T, class U> auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) < std::forward<U>(u));
    typedef *unspecified* is_transparent;
};

例如,std::set

这解决了什么问题?这会改变标准容器的工作方式吗?例如,std::set的模板参数仍然是Key,Compare=std::less


共有3个答案

司马彬
2023-03-14

以下是n3657的所有副本

问:使比较国“透明”的目的是什么?

A.关联容器查找函数(查找、lower_bound、upper_bound、equal_range)只接受key_type的参数,要求用户构造(隐式或显式)key_type的对象来进行查找。这可能是昂贵的,例如当比较器函数只查看对象的一个字段时,构建一个大对象以在集合中搜索。用户强烈希望能够使用与key_type相当的其他类型进行搜索。

这能解决什么问题

A.LWG对以下代码表示关注:

std::set<std::string> s = /* ... */;
s.find("key");

在C 11中,这将构造一个std::string temporary,然后将其与元素进行比较以找到键。

通过N3465提出的更改,std::集::find()函数将是一个不受约束的模板,它将把const char*传递给比较器函数,std::less,后者将构造std::字符串临时为每个比较。LWG认为这一性能问题是一个严重的问题。模板查找()函数还将防止在指针容器中查找NULL,这将导致以前有效的代码不再编译,但这被视为比无声性能回归不那么严重的问题

这是否改变了标准容器的工作方式

A.此方案通过使用成员函数模板重载查找成员函数来修改和中的关联容器。没有语言变化。

默认集也会丢失它的查找、计数等成员

答:几乎所有现有的C 11代码都不受影响,因为除非使用新的C 14库特性作为比较函数,否则成员函数不存在。

引用雅克的话,

在C 14中,如果存在Compare::is_transparent,则std::set::find是一个模板函数。传入的类型不需要是键,只需在比较器下等效即可。

和n3657,

在23.2中添加第13段。4[associative.reqmts]:成员函数模板find、lower_bound、upper_bound和equal_range不得参与重载解析,除非类型Compare::是透明的 不存在 确实存在。

N3421提供了“透明运算符函数”的示例。

完整的代码在这里。

通安宁
2023-03-14

在C11中没有成员模板search()lower_bound()等。也就是说,这种变化不会损失任何东西。n3657引入了成员模板,以允许异构键与关联容器一起使用。除了好的和坏的例子,我没有看到任何具体的例子说明这是有用的!

是透明的用途旨在避免不必要的转换。如果成员模板不受约束,现有代码可能会直接通过对象,而这些对象在没有成员模板的情况下会被转换。n3657中的示例用例是在std::集合中定位对象

比较函数对象中嵌套is_transparent类型提供了一种指定是否应该使用模板化成员函数的方法:如果比较函数对象可以处理异构参数,它定义这种类型以表明它可以高效地处理不同的参数...例如,新的运算符函数对象只是委托给运算符

公孙宇
2023-03-14

这解决了什么问题,,

见迪特玛和雷米亚贝尔的答案。

这会改变标准容器的工作方式吗?

不,不是默认的。

新的成员函数模板重载find等。允许您使用与容器的键类似的类型,而不是使用键类型本身。有关添加此功能的基本原理和详细、仔细编写的建议,请参见Joaqín MªLópez Muñoz的N3465。

在布里斯托尔会议上,LWG一致认为,十六进制查找功能是有用和可取的,但我们不能确定华金的提议在所有情况下都是安全的。N3465提案会给一些程序带来严重问题(见对现有代码部分的影响)。Joaquín准备了一份更新的提案草案,其中包含了一些具有不同权衡的替代实现,这非常有助于LWG理解利弊,但他们都冒着以某种方式破坏一些程序的风险,因此没有达成添加该功能的共识。我们决定,尽管无条件添加该功能不安全,但如果默认情况下禁用该功能,并且只“选择加入”,这将是安全的。

N3657提案(这是我和STL在N3465基础上的最后一次修订,也是Joaquin后来未发布的草案)的关键区别在于添加了is_transparent类型作为可用于选择加入新功能的协议。

如果您不使用“透明函子”(即定义是透明的类型的函子),那么容器的行为与它们一贯的行为相同,这仍然是默认行为。

如果您选择使用std::less

使用std::less

template<typename T, typename Cmp = std::less<>, typename Alloc = std::allocator<T>>
  using set = std::set<T, Cmp, Alloc>;

名称is_transparent来自STL的N3421,它将“钻石运算符”添加到C14。透明仿函数是接受任何参数类型(不必相同)并简单地将这些参数转发给另一个运算符的函数。这样的仿函数恰好是关联容器中异构查找所需要的,因此类型is_transparent被添加到所有菱形运算符中,并用作标记类型来指示新功能应该在关联容器中启用。从技术上讲,容器不需要透明仿函数,只需要支持用异构类型调用它的仿函数(例如https://stackoverflow.com/a/18940595/981959中的pointer_comp类型根据STL的定义不是透明的,而是定义pointer_comp::is_transparent允许用于解决问题)。如果你只在你的std::中查找

 类似资料:
  • 本文向大家介绍请你说明符号“==”比较的是什么?相关面试题,主要包含被问及请你说明符号“==”比较的是什么?时的应答技巧和注意事项,需要的朋友参考一下 考点:基础 “==”对比两个对象基于内存引用,如果两个对象的引用完全相同(指向同一个对象)时,“==”操作将返回true,否则返回false。“==”如果两边是基本类型,就是比较数值是否相等。

  • 问题内容: 在Swing中,JPanel表示是不透明的,这意味着什么? 还有JPanel VS JComponent与不透明相比如何? 请尽可能简单地解释一下,因此我在GUI编程方面不是很有经验。 在此先感谢您的帮助 问题答案: Opaque在Swing中具有非常特殊的含义-这意味着该组件在其边界内完全绘制了整个区域(请参见setOpaque javadoc ) 这主要用于确定是否有必要在当前组件

  • 我有以下功能,PyCharm正在提醒我关于“简化链式比较”的语句。代码工作,我得到了我想要的对象,只是想知道警告以及如何使其更好?

  • 内网穿透是我们在进行网络连接时的一种术语,也叫做NAT穿透,内网穿透的功能就是,当我们在端口映射时设置时,内网穿透起到了地址转换的功能。 内网穿透的原理很简单的说就是: 两台计算机A和B都处于不同的局域网中,A想要访问B, 就需要通过一台服务器做桥接的,桥接的方式有两种,一种是服务器相互转发流量 到A和B,另一种是告诉对方公网IP地址,自己充当一个介绍人的角色, 专业术语叫DNAT目标地址转换。

  • 问题内容: 好吧,我有两个StringBuilder对象,我需要在Java中对其进行比较。我知道我可以做的一种方法是 但这意味着我要创建两个String对象,还有没有更好的方法来比较StringBuilder对象。也许您不需要创建其他对象的地方? 问题答案: 如您所知,继承自,因此仅在将同一对象作为参数传递时才返回true。它并 没有 比较两个内容小号! 如果您查看源代码,您将得出结论,最有效的比

  • 本文向大家介绍Object.is()和比较操作符"="的区别是什么?相关面试题,主要包含被问及Object.is()和比较操作符"="的区别是什么?时的应答技巧和注意事项,需要的朋友参考一下 Object.is()类似于===,但在三等号判等的基础上特别处理了 NaN 、-0 和 +0 ,保证 -0 和 +0 不再相同,但 Object.is(NaN, NaN) 会返回 true。