Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map::const_iterator mapped type is not const

Tags:

c++

I'm trying to write an iterator adaptor for a class built on top of a map. I'm having issue when trying to get the mapped type from the iterator type. Basically I'd like to get:

  • map<Key,Val>::iterator --> Val
  • map<Key,Val>::const_iterator --> Val const

Here is a minimal repro.

#include <map>
#include <type_traits>
    
template <typename BaseIteratorT>
using ValueType = typename BaseIteratorT::value_type::second_type;
    
// Passes
static_assert(
    std::is_same<ValueType<std::map<double, int>::iterator>, int>::value,
    "bad type for mutable iterator");

// Fails
static_assert(
    std::is_same<ValueType<std::map<double, int>::const_iterator>, const int>::value,
    "bad type for const iterator");

How can I achieve that (C++14)?

like image 662
brice rebsamen Avatar asked Sep 01 '20 22:09

brice rebsamen


2 Answers

For almost all practical purposes, types you might want to deduce is tied to some expression, in which case decltype is always the answer

template<typename T>
using mapped_type = std::remove_reference_t<decltype((std::declval<T>()->second))>;

using m = std::map<char, int>;
using i = mapped_type<m::iterator>  // int
using ci = mapped_type<m::const_iterator>  // const int
like image 162
Passer By Avatar answered Oct 19 '22 18:10

Passer By


The value_type of a std::map is std::pair<const Key, T>. The second_type of that pair is just T, not const T, not const T&, just T. Dereferencing a map::const_iterator will return a const pair& reference, but that will not change that pair's second_type to const. If you want that, detect whether the iterator's value_type is const or not, such as with std::is_const, and if so then apply const to its second_type, such as with std::add_const.

like image 25
Remy Lebeau Avatar answered Oct 19 '22 18:10

Remy Lebeau