map :: const_iterator il tipo mappato non è const

Sep 02 2020

Sto cercando di scrivere un adattatore iteratore per una classe costruita sopra una mappa. Ho problemi durante il tentativo di ottenere il tipo mappato dal tipo iteratore. Fondamentalmente mi piacerebbe ottenere:

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

Ecco una riproduzione minima.

#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");

Come posso ottenerlo (C ++ 14)?

Risposte

2 PasserBy Sep 02 2020 at 08:18

Per quasi tutti gli scopi pratici, i tipi che potresti voler dedurre sono legati a qualche espressione, nel qual caso decltypeè sempre la risposta

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
2 RemyLebeau Sep 02 2020 at 07:54

Il value_typedi un std::mapè std::pair<const Key, T>. Il valore second_typedi quella coppia è solo T, non const T, non const T&, solo T. Dereferenziare a map::const_iteratorrestituirà un const pair&riferimento, ma ciò non cambierà quella coppia second_typein const. Se lo desideri, rileva se l'iteratore value_typeè consto meno, come con std::is_const, e in tal caso applicalo constal suo second_type, come con std::add_const.