How to select iterator type using auto variable?
Asked Answered
A

1

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?

Aesop answered 26/2, 2012 at 13:16 Comment(2)
Perhaps the compiler is doing function-wide type inference... But why does the constness of the iterator matters to you?Gilliam
Unless my understanding of overloading is wrong (or 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.Tamarah
I
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");
Its answered 26/2, 2012 at 13:24 Comment(5)
Why not just template<typename T> const T& const_(T& t) { return t; } ?Smackdab
That will not work with nonconst rvalues and will transform const rvalues to lvalues. not good.Its
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.Smackdab
It keeps rvalues as rvalues and lvalues as lvalues so that ref qualifier overloading of memberfunctions still work.Its
c++17 has added std::as_const to the header <utility> linkKerriekerrigan

© 2022 - 2024 — McMap. All rights reserved.