13

I have a std::unordered_map

std::unordered_map<std::string, std::string> myMap;

I want to get a const iterator using find. In c++03 I would do

std::unordered_map<std::string, std::string>::const_iterator = myMap.find("SomeValue");

In c++11 I would want to use auto instead to cut down on the templates

auto = myMap.find("SomeValue");

Will this be a const_iterator or iterator? How does the compiler decide which to use? Is there a way I can force it to choose const?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Jim Jeffries
  • 9,841
  • 15
  • 62
  • 103
  • 1
    Perhaps the compiler is doing function-wide type inference... But why does the constness of the iterator matters to you? – Basile Starynkevitch Feb 26 '12 at 13:19
  • 4
    Unless my understanding of overloading is wrong (or http://en.cppreference.com/w/cpp/container/unordered_map/find is wrong), `nonConstMap.find` always returns an `iterator`. The return type and what you do with the result (e.g. pass it to a `const_iterator` constructor) does not affect which overload is chosen. That is, it only returns a `const_iterator` if you call `constMap.find`. –  Feb 26 '12 at 13:26

1 Answers1

8

It will use non-const iterators if myMap is a non-const expression. You could therefore say

#include <type_traits>
#include <utility>

template<typename T, typename Vc> struct apply_vc;
template<typename T, typename U> struct apply_vc<T, U&> {
  typedef T &type;
};
template<typename T, typename U> struct apply_vc<T, U&&> {
  typedef T &&type;
};

template<typename T> 
typename apply_vc<typename std::remove_reference<T>::type const, T&&>::type
const_(T &&t) {
  return std::forward<T>(t);
}

And then

auto it = const_(myMap).find("SomeValue");
Lauri Nurmi
  • 566
  • 1
  • 3
  • 14
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Why not just `template const T& const_(T& t) { return t; }` ? – MSalters Feb 27 '12 at 10:52
  • 1
    That will not work with nonconst rvalues and will transform const rvalues to lvalues. not good. – Johannes Schaub - litb Feb 27 '12 at 11:47
  • I hadn't considered the latter (why make something `const` which is already `const`?), but you'd trivially solve that with an overload anyway. The rvalue case is good, but I'm still trying to wrap my head around `apply_vc`. I see _what_ it does, but not why it's necessary. – MSalters Feb 27 '12 at 13:28
  • 1
    It keeps rvalues as rvalues and lvalues as lvalues so that ref qualifier overloading of memberfunctions still work. – Johannes Schaub - litb Feb 27 '12 at 19:15
  • c++17 has added std::as_const to the header [link](http://en.cppreference.com/w/cpp/utility/as_const) – ChetS Aug 19 '16 at 22:00