推导出类型“auto it = unordered_map.find(key)”?

时间:2013-08-21 18:41:45

标签: c++11 const-iterator

随着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;
}

2 个答案:

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

这有点不足;我们有cbegincend但没有相应的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