假设您有一个std::unordered_set<std::string>
。
您std::string_view
在容器中有一个要搜索的对象。问题是,您不想std::string
从自己创建一个std::string_view
,因为这种破坏std::string_view
首先要使用的目的。
但是,似乎std::string_view
应该可以将其用作密钥。应该有一些方法来比较std::string_view
和std::string
改变,因为它们基本上代表了同样的事情。但是无论如何,STL中都没有。
这是一个僵局,我是否被迫编写自己的比较对象std::string_view
以及std::string
与之配合使用的对象std::unordered_set
?
编辑:此问题特定于string_view对象。“重复”问题无关紧要。正如预期的那样,我收到了一个独特问题的独特答案。
我没有一个很好的解决方案,但一个可能的解决方法用最少的自定义代码,以提高内存的使用费用,将取代你std::unordered_set<std::string>
与一个std::unordered_map
有观点的钥匙,和字符串值(背视图)。
不幸的是,由于进行了小的字符串优化,我们不能依靠std::move
保留基础string
数据的原始地址,因此类似:
std::string to_insert(...);
mymap.try_emplace(to_insert, std::move(to_insert));
无法正常工作。
相反,它必须是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));
尽管插入有点麻烦,但是简单的成员资格测试将保持简单,因为std::string
定义了一个隐式operator std::string_view
,并且std::string_view
具有的隐式构造函数char*
,所以成员资格测试仍然很简单:
if (mymap.count(some_string)) { ... }
是否some_string
是一个char*
,std::string_view
或std::string
。
注意:我不会发誓基于两行try_emplace
代码的插入代码是合法的,因为我在C ++上有些实践,并且对于unique_ptr
在move
从中使用相同的表达式中使用a持谨慎态度;在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));
附加说明:只有在emplace
/ emplace_hint
/try_emplace
功能,可以安全地用于更新条目mymap
中这样的设计。如果在构建地图时两次遇到相同的键,则使用mymap[key] = std::move(to_insert);
或insert_or_assign
中断,因为将保留原始键string_view
(引用原始string
数据),同时将值替换为new string
,从而使string_view
的指针无效。虽然insert
不替换值,但我相信使用它将需要更像具有3衬线的设计try_emplace
,因为std::pair
如果您尝试同时构造视图和构造的unique_ptr
一部分,则使插入插入的顺序将是无序的pair
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句