6

随着 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 iterator”,但我强烈怀疑“const iterator”是同一个“const_iterator”,其中“const iterator”有限制更改迭代器本身的能力,而“const_iterator”限制了更改迭代器所指内容的能力。

所以,真的,如果我们想充分利用“auto”类型推导(了解混淆或“auto”类型推导的变体 - 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;
}
4

2 回答 2

1

这有点不足;我们有cbegincend没有对应cfind的等。

我建议使用实用程序函数来获取对对象的 const 引用,根据在基于范围的 for 中强制使用 cbegin()/cend()的答案:

template<typename T> constexpr const T &as_const(T &t) { return t; }

auto it1 = as_const(umii).find(0);
it1->second = 42; // fails
于 2013-08-21T19:35:16.600 回答
1

我不知道有什么地方需要const_iterator你不能简单地通过iterator,所以这种缺陷可能不会对日常代码编写产生太大影响。但是,为了一般的交流,我更喜欢在不需要变异的地方使用const_iterators (一般来说),所以我认为添加 a可能是对未来标准库的有用补充。constcfind()

不过,我认为这段代码可以作为您想要实现的目标的简单解决方法:

template<typename T>
auto use_as_const( T const &t ) -> T const & {
    return t;
}

这是一个简单的强制转换包装函数,在样式上类似于move()and forward<T>(),用于提供(和记录)对对象的各个使用的约束。然后你可以像这样使用它:

auto it1 = use_as_const( umii ).find(0);

这也可以用来代替依靠cbegin()and 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 引用。

于 2013-08-21T19:36:03.263 回答