使用常量键

时间:2018-03-24 18:29:21

标签: c++ stl language-lawyer

无序设置键是只读的,所以为什么在这种情况下我可以擦除元素:

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>); }

2 个答案:

答案 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;

相关问题