无序设置键是只读的,所以为什么在这种情况下我可以擦除元素:
std::unordered_set<std::string> s;
s.emplace("sth");
s.erase("sth");
而在此不是:
std::unordered_set<std::string const> s;
const std::string str("sth");
s.emplace(str);
s.erase(str);
如果设置本身就是const它会有意义但是使用const键我不太明白。这个断言失败了:
static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
为什么会写那个断言的人,检查密钥是不是const?
修改
事实上,上面的代码可以很好地编译std::set
。对于std::unordered_set
,失败直接在实例化时发生。重现的最小例子:
// define a customized hash ...
int main() { sizeof(std::unordered_set<int const>); }
答案 0 :(得分:1)
你无法擦除元素的原因不是因为const-correctness。
这是因为你不能拥有const的容器。这是不允许的。
你违反了unordered_set
的合同。
static_assert
检测到了。
答案 1 :(得分:0)
我认为你缺少的是std :: set实际上分配了自己的字符串。所以当你说s.emplace(&#34; sth&#34;)时,它会创建一个新的&#34; sth&#34;字符串,它不使用你的(它用它来构造一个新的)。 为什么这些新分配的字符串是const?因为您不想直接修改它们,否则您将破坏该集合。如果你改变了#a; aaa&#34;到&#34; zzz&#34;直接然后该集合仍将认为&#34; zzz&#34;是&#34; bbb&#34;。
之前的集合中的第一个元素那为什么断言呢? 因为std没有const对象的分配器 - 所以当它尝试分配const对象时,它将失败。 他的VS2017错误更明显: &#34; C ++标准禁止使用const元素的容器,因为分配器格式不正确。&#34;