le type mappé map :: const_iterator n'est pas const

Sep 02 2020

J'essaie d'écrire un adaptateur d'itérateur pour une classe construite au-dessus d'une carte. J'ai un problème en essayant d'obtenir le type mappé à partir du type d'itérateur. En gros, j'aimerais obtenir:

  • map <Clé, Val> :: itérateur -> Val
  • map <Clé, Val> :: const_iterator -> Val const

Voici un repro minimal.

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

Comment puis-je y parvenir (C ++ 14)?

Réponses

2 PasserBy Sep 02 2020 at 08:18

Pour presque toutes les raisons pratiques, les types que vous voudrez peut-être déduire sont liés à une expression, auquel cas decltypeest toujours la réponse

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

Le value_typed'un std::mapest std::pair<const Key, T>. Le second_typede cette paire est juste T, non const T, non const T&, juste T. Déréférencer a map::const_iteratorrenverra une const pair&référence, mais cela ne changera pas cette paire second_typeen const. Si vous le souhaitez, détectez si l'itérateur value_typeest constou non, par exemple avec std::is_const, et si c'est le cas, appliquez-le constà son second_type, par exemple avec std::add_const.