Ada*_*dam 10 c++ stl unordered-set string-view c++17
假设您有一个std::unordered_set<std::string>
.
您有一个std::string_view
要在容器中搜索的对象。问题是,您不想std::string
从您的 中创建 a std::string_view
,因为这种首先违背了使用的目的std::string_view
。
不过,好像std::string_view
应该可以作为key使用;应该有某种方式来比较std::string_view
and std::string
,因为它们基本上代表同一件事。但是没有,无论如何都没有在 STL 中。
这是一个僵局,我是否被迫编写自己的比较对象std::string_view
并std::string
与我的对象一起使用std::unordered_set
?
编辑:这个问题特定于 string_view 对象。“重复”问题不相关。正如预期的那样,我收到了一个独特问题的独特答案。
我没有一个很好的解决方案,但一个可能的解决方法是使用最少的自定义代码,以增加内存使用量为代价,将您的替换为具有键视图和值字符串(支持视图)的std::unordered_set<std::string>
a 。std::unordered_map
不幸的是,由于小字符串优化,我们不能依赖于std::move
保留底层数据的原始地址string
,所以类似:
std::string to_insert(...);
mymap.try_emplace(to_insert, std::move(to_insert));
Run Code Online (Sandbox Code Playgroud)
是行不通的。
相反,它必须是 a,std::unordered_map<std::string_view, std::unique_ptr<std::string>>
这样我们就可以保留字符串字符的唯一地址,使代码更像:
auto to_insert = std::make_unique<std::string>(...);
mymap.try_emplace(*to_insert, std::move(to_insert));
Run Code Online (Sandbox Code Playgroud)
虽然插入有点难看,但简单的成员资格测试仍然很简单,因为std::string
定义了一个隐式operator std::string_view
,并且std::string_view
有一个隐式构造函数char*
,所以成员资格测试仍然很简单:
if (mymap.count(some_string)) { ... }
Run Code Online (Sandbox Code Playgroud)
是否some_string
是char*
,std::string_view
或std::string
.
注意:我不会发誓try_emplace
基于两行的插入代码是合法的,因为我对 C++ 有点缺乏实践,并且对在我从中获取的unique_ptr
同一表达式中使用 a 持谨慎态度;move
在g++
7.2 上,它似乎有效,并且我认为立即构造的关键参数try_emplace
,而构造值的参数被转发使得这很安全,但我承认我对 C++ 求值顺序的理解(或缺乏) )并不完美。如果我做了一些非法的事情,而不仅仅是丑陋的事情,那么修复它需要稍微丑陋的(但肯定是按顺序的):
auto to_insert = std::make_unique<std::string>(...);
std::string_view key{*to_insert};
mymap.try_emplace(std::move(key), std::move(to_insert));
Run Code Online (Sandbox Code Playgroud)
附加说明:只有emplace
//函数可以安全地emplace_hint
用于更新此设计try_emplace
中的条目。如果在构建映射时两次遇到相同的键,则mymap
使用mymap[key] = std::move(to_insert);
或中断,因为原始的(引用原始的数据)将被保留,而值将被新的替换,从而使的指针无效。虽然不替换值,但我相信使用它需要更像带有 的三行的设计,因为如果您尝试构建视图并作为构建的一部分,则插入将是无序的。insert_or_assign
string_view
string
string
string_view
insert
try_emplace
std::pair
unique_ptr
pair
归档时间: |
|
查看次数: |
3516 次 |
最近记录: |