Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the 'auto' keyword know when to use a const_iterator matching function overloads?

I understand the content of this question but how do things work when function overloads are used?

For instance in std::map the following methods are defined:

      iterator find (const key_type& k);
const_iterator find (const key_type& k) const;

How is it possible to pick one or the other using the auto keyword? Something like the following does not seem correct to me:

auto i = mymap.find(key);        //calls the non-const method?
const auto i = mymap.find(key);  //calls the const method?
like image 810
DarioP Avatar asked Feb 12 '14 12:02

DarioP


2 Answers

std::map<int, int> mutable_map;
const std::map<int, int> const_map;

mutable_map.find(1); // returns iterator
const_map.find(1);   // returns const_iterator

You would not want to return a regular iterator from a constant map because that would undermine the constness. So the only way to have a find member function that works sensibly with constant maps is to have a const overload that returns a const_iterator.

like image 117
JohannesD Avatar answered Nov 15 '22 00:11

JohannesD


In c++14, you will have cbegin and cend to enforce a const_iterator getter.

To do the same with the map's find methods, you need const_cast but the syntax is horrible or a small helper.

#include <iostream>
#include <map>

template <typename T> T const &  ccast( T const & v )  { return v; }
template <typename T> T const && ccast( T const && v ) { return v; }

int main() {
    using Map = std::map<int,int>;
    Map map;

    static_assert( std::is_same< decltype(map.find(1)), Map::iterator >::value, " mutable map give mutable iterator" );
    static_assert( std::is_same< decltype(const_cast<Map const&>(map).find(1)), Map::const_iterator >::value, "const map give imutable iterator" );

    static_assert( std::is_same< decltype(ccast(map).find(1)), Map::const_iterator >::value, "const map give imutable iterator" );
    static_assert( std::is_same< decltype(ccast(std::move(map)).find(1)), Map::const_iterator >::value, "const map give imutable iterator" );
}

But for a map, calling the mutable find and storing as a const iterator at the assignment is the simplest, note that it will prevent iterating from it after that

auto const it = map.find(1);
it++ // compilation error
std::for_each( it, end(map), /**/ ); // compilation error too
like image 31
galop1n Avatar answered Nov 14 '22 23:11

galop1n