我没有一个很好的解决方案,但是以最少的自定义代码为代价的一种可能的解决方法是,以增加内存使用量为代价,将您的替换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
注意:我不会发誓基于两行代码的插入代码是合法的,因为我在 C++ 上有点不习惯,并且对在我从中使用的同一表达式中try_emplace
使用 a 持怀疑态度;在7.2 上它似乎有效,我认为关键参数是立即构造的,而构造值的参数被转发使得这很安全,但我承认我对 C++ 评估顺序的理解(或缺乏) 并不完美。如果我正在做一些非法的事情,而不仅仅是丑陋,那么修复它需要稍微丑陋一些(但肯定是有序的):unique_ptr
move
g++
try_emplace
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
string
string_view
insert
try_emplace
std::pair
unique_ptr
pair