map :: const_iterator mapped type nie jest const

Sep 02 2020

Próbuję napisać adapter iteratora dla klasy zbudowanej na mapie. Mam problem, gdy próbuję uzyskać mapowany typ z typu iteratora. Zasadniczo chciałbym uzyskać:

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

Oto minimalna kopia.

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

Jak mogę to osiągnąć (C ++ 14)?

Odpowiedzi

2 PasserBy Sep 02 2020 at 08:18

Niemal ze wszystkich praktycznych powodów typy, które możesz chcieć wydedukować, są powiązane z jakimś wyrażeniem, w którym decltypeto przypadku zawsze jest odpowiedź

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

Z value_typea std::mapjest std::pair<const Key, T>. Ta second_typepara jest po prostu T, nie const T, nie const T&, tylko T. Dereferencja a map::const_iteratorzwróci const pair&odwołanie, ale nie zmieni wartości tej pary second_typena const. Jeśli chcesz, wykryj, czy iterator value_typejest, constczy nie, na przykład with std::is_const, a jeśli tak, zastosuj constgo second_type, na przykład with std::add_const.