6
std::map<char,int> dict;
...
auto pmax = dict.begin(); // here i get const iterator

Can I "explicitly indicate" that the value obtained is a non-constant type?

ObiSan
  • 247
  • 4
  • 14
  • If you like to have it short, use a `typedef` to create an alias for an iterator like `typedef std::map::iterator MCIIT;`, but refrain from using to much `auto` – bash.d Apr 02 '13 at 07:40
  • 11
    Unless `dict` is const, you're not getting a const iterator with that code. It's just that the `pmax->first` is const, because that's the way maps work. They maintain their order by the key, and so that key must not be modifiable. – Benjamin Lindley Apr 02 '13 at 07:40
  • ahah here’s the nice example of how bad is programing teachers: they tell you things without explainations. – phaazon Apr 02 '13 at 07:40
  • You should post a complete example, because there are several open questions about your code. – Björn Pollex Apr 02 '13 at 07:40
  • possible duplicate of [How to select iterator type using auto variable](http://stackoverflow.com/questions/9453383/how-to-select-iterator-type-using-auto-variable) – Björn Pollex Apr 02 '13 at 07:42
  • What do you actually want to do? A [short](http://ideone.com/GmtpDq) experiment shows, you can modify the `pmax->second` – Dmitry Ledentsov Apr 02 '13 at 08:07

2 Answers2

3

If your dict is not const, begin will return a std::map<char,int>::iterator. Now, the key is const, but the value is not.

auto should give you a std::map<char,int>::iterator; do you have evidence to the contrary?

Alex Chamberlain
  • 4,147
  • 2
  • 22
  • 49
  • 1
    @ObiSan: Return value of what? I have MSVC 2012 and its behavior regarding the return value of `std::map::begin` is perfectly normal. It returns `std::map::iterator`, who's value_type is `std::pair`. You'll need to present a complete example that demonstrates your problem. – Benjamin Lindley Apr 02 '13 at 07:52
  • @ObiSan That's useless; it's ignoring `auto`. – Alex Chamberlain Apr 02 '13 at 08:11
  • 1
    @ObiSan: A description about the problem you are having with the code would also be nice. I presume your issue is that, when you uncomment the commented code, `*pmax = p;` does not compile. That problem is explained in this answer, and in my comment below your question. The iterator is not const. The key value is const. This is necessary in order for a map to maintain its order. If the iterator was const, the mapped value would also be const. Try `pmax->second = 10;`, and you will see that it is not. – Benjamin Lindley Apr 02 '13 at 08:14
  • Yes. Sorry for debug version. If i uncomment the commented code, i get error in line '*pmax = p' - like "l-value is pointing to an object-constant (const)". – ObiSan Apr 02 '13 at 08:27
0

Looking at your code, you are basically implementing std::max_element. So you could rewrite your last output line to:

    std::cout << std::max_element(begin(dict), end(dict),
        [](decltype(*begin(dict)) a, decltype(*begin(dict)) b) {
            return a.second < b.second;
        })->first << std::endl;

Admittedly, the decltype(*begin(dict)) is ugly, which hopefully will be remedied by generic lambdas in C++1y.

The point is, that regardless of whether you have a map::iterator or map::const_iterator when you dereference it, the result will be a std::pair with a const key_type as first argument. So, even if you have two iterators it1, it2 to mutable data (e.g., acquired via map::begin()), you can not re-assign the complete pair that is referenced by those iterators. Thus, *it1 = *it2 won't work, because you are trying to overwrite the mapped_type and the const key_type.

Community
  • 1
  • 1