随着C ++ 11的出现,我们将unordered_map.cbegin / cend专门返回给我们const_iterator的值。所以表达式“auto it = unordered_map.cbegin()”中推导出的'it'类型是const_iterator。
然而,当谈到unordered_map.find(key)函数时,我认为可能缺少一个“cfind()”对应物,它会特别返回一个const_iterator。
有人说我们可以使用“const auto it = unordered_map.find(key)”来获取“const迭代器”,但我强烈怀疑“const iterator”是相同的“const_iterator”,其中“const”迭代器“限制了更改迭代器本身的能力,而”const_iterator“限制了更改迭代器引用的内容的能力。
所以,真的,如果我们想充分利用“自动”类型演绎(了解混淆或“自动”类型演绎的变化 - auto,auto&,const auto&等),我怎么能让unordered_map.find(key)返回一个“const_iterator”,而不必显式指定“const_iterator” - 这就是auto的所有最佳用例之后!
下面是一个演示编译器行为的简单示例代码:
#include "stdafx.h"
#include <unordered_map>
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::unordered_map<int, int> umiit;
umiit umii;
auto it0 = umii.find(0);
it0->second = 42;
const auto it1 = umii.find(0);
it1->second = 42;
umiit::const_iterator it2 = umii.find(0);
it2->second = 42; // expected compiler error: assigning to const
return 0;
}
答案 0 :(得分:2)
我不知道任何需要const_iterator
的地方,你不能简单地传递iterator
,所以这种不足可能不会干扰日常的代码编写。但是,为了一般的沟通,我更喜欢在不需要变异的地方使用const_iterator
s(和const
),所以我认为添加cfind()
可能是对未来标准库的有用补充。
我认为这段代码可以作为您尝试实现的目标的简单解决方法:
template<typename T>
auto use_as_const( T const &t ) -> T const & {
return t;
}
这是一个简单的转换包装函数,类似于move()
和forward<T>()
的样式,用于提供(和文档)对象的各个用法的约束。然后你可以像这样使用它:
auto it1 = use_as_const( umii ).find(0);
这也可以用来代替cbegin()
和cend()
。或者,它可以用于基于范围的for循环:
for ( auto &element : use_as_const( some_vector_of_string ) ) {
cout << element;
// element = ""; // This line shouldn't compile.
}
在上面的循环示例中,虽然我通常更喜欢auto const &element : ...
,但我认为这是不必要的,element
仍然会被推断为const引用。
答案 1 :(得分:1)
这有点不足;我们有cbegin
和cend
但没有相应的cfind
等等。
根据forcing use of cbegin()/cend() in range-based for的答案,我建议使用实用程序函数来获取对象的const引用:
template<typename T> constexpr const T &as_const(T &t) { return t; }
auto it1 = as_const(umii).find(0);
it1->second = 42; // fails