为什么在 C++ 中选择加入异构 std::*map 查找? [重复]

问题描述 投票:0回答:2

为了支持

std::map
的异构密钥查找,必须比过去更详细一点:(摘自关于如何做到这一点的问题

int main()
{
    {
        puts("The C++11 way makes a copy...");
        std::map<std_string, int> m;
        auto it = m.find("Olaf");
    }
    {
        puts("The C++14 way doesn't...");
        std::map<std_string, int, std::less<>> m;
        auto it = m.find("Olaf");
    }
}

另请参阅:https://www.cppstories.com/2021/heterogeneous-access-cpp20/ 获取解释。

从这个链接和链接的问题(以及N3657)中,给出了一些关于为什么选择加入的分散原因。由于我必须进行相当多的滚动操作,并且没有找到简洁的原因总结,因此我想在这里整理一个每个初级开发人员都理解的总结,至于

为什么愚蠢的 C++ 让我多写一些

std::less<>
??!为什么它不只允许与我们一直使用的默认类型进行透明的异构比较?

;-)

c++ containers c++14
2个回答
2
投票

如果

std::map
简单地默默支持这一点,也就是说,如果
std::map<KeyT, ValT>
会支持“任何兼容”类型的
find(LookupT)
,那么:

  • 关于此事的abseil页面引用了
    double
    int
    之间的隐式比较,这会很麻烦:

隐式支持异构查找可能很危险,因为关系 转换后可能无法保留值之间的关系。 例如,

1.0 < 1.1
,但是
static_cast<int>(1.0) == static_cast<int>(1.1)
。 因此,使用
double
查找
std::set<int>
中的值可能会导致不正确的结果。

  • 性能(!) - 不支持异构比较的类型的旧代码将开始运行变慢dyp写道

考虑某些类型

stupid_string
仅存在一个转换构造函数 来自
char const*
,但不是比较运算符
operator<(stupid_string const&,  char const*)
,仅
operator<(stupid_string const&, stupid_string const&)
。 由于
std::less<>
((would)) 转发到比较运算符,因此每次比较都会创建一个新的 Stud_string。

((而不是仅仅在 std::find 的调用站点上创建一次额外的比较对象))


1
投票

map
模板有默认比较

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

假设您想要一个

map<my_type, int>
并通过专门化
std::less<my_type>
(然后默认选择)来启用它。

那么 C++14 就不能开始使用非专门化的

std::less<>
来代替。所以你必须明确要求!

© www.soinside.com 2019 - 2024. All rights reserved.