2016-11-09 32 views
2

给定std::set< T, less >std::map< T, less >容器中的独特元素。 less是异构比较器。即它可以将一些另外的类型U的值与类型T的值进行比较。尽管T类型的所有值都是唯一的,但是(可能)有大量值为T的值,它们的值等于U类型的某个特定值。它是不确定的行为?映射或设置有透明比较器和异构元素的非唯一元素

说,我想在容器中找到(一个)元素,它具有键值,相当于U类型的值。任何一个:无论是第一个,最后一个还是其中的一个,如果多于一个。我知道,容器中有多个元素,它们相当于U类型的值u。我可以使用std::set::findstd::map::find功能吗?是未定义的行为

实施例(在此不精确公差0.2比较):

#include <set> 
#include <iostream> 

double const eps = 0.2; 

struct less 
{ 
    bool operator() (double l, double r) const { return l < r; } 
    using is_transparent = void; 
    bool operator() (int l, double r) const { return l + eps < r; } 
    bool operator() (double l, int r) const { return l + eps < r; } 
}; 

int main() 
{ 
    std::set< double, less > s{0.0, 0.9, 1.0, 1.1, 2.0}; 
    for (auto it = s.find(1); it != std::end(s); it = s.find(1)) { 
     std::cout << *it << ' '; 
     s.erase(it); 
    } 
} 

输出(顺序通常未指定):

0.9 1 1.1

是否UB使用缔有序如上所述的独特元素的容器?

应该用std::multiset还是std::multimap代替?

+0

我认为你的意思是“大量的**'U' **值等于给定的'T'” –

+0

你的例子'less'在比较int和double时没有定义严格的弱排序。这看起来很可能是悲伤的原因。 OTOH,比较像'operator()(std :: pair lhs,double rhs){return lhs.first

+0

@MartinBonner号完全如上所述。上面的例子说明了这种可能 – Orient

回答

1

关联容器要求表之前的解释性文本说:

kl是一个值,使得a [原文如此]被分区([alg.sorting]) 相对于c(r, kl),与ree的关键值 a; kua相对于分割的值; kea相对于 到c(r, ke)!c(ke, r)划分的值,其中c(r, ke)暗示!c(ke, r)

,然后介绍的a_tran.{find,count,equal_range}(ke)a_tran.lower_bound(kl)a_tran.upper_bound(ku)行为。因此,要求是:

  • 对于findcount,和equal_range
    • 在容器中的元素必须相对于被分割到c(r, ke)!c(ke, r)
    • c(r, ke)必须隐含!c(ke, r)
  • 对于lower_bound,容器中的元素必须根据c(r, kl)进行分区。
  • 对于upper_bound,容器中的元素必须根据!c(ku, r)进行分区。

如果您满足这些要求,那么在容器中使用与多个键等效的东西来使用异构查找没有任何问题。毕竟,the original proposal中的激励性示例是关于在名称的set中查找姓氏为“Smith”的所有人。