Способ конвертировать итератор в const_iterator - PullRequest
1 голос
/ 23 марта 2019

Я пишу контейнерное представление, параметризованное итератором, и мне нужно знать тип const_iterator. Как то так:

template <typename It>
// It = random access iterator
class Container_view{
    using value_type = typename std::iterator_traits<It>::value_type;
    using reference  = ...
    ...

    using iterator = It;
    using const_iterator = ???
};

Как узнать тип const_iterator от итератора?


Редактировать: способ конвертировать итератор в const_iterator с помощью этого кода:

// about dependent_false: https://en.cppreference.com/w/cpp/language/if
template <typename T>
struct dependent_false : std::false_type { };


// has_const_iterator is true if has const_iterator member, otherwise
// is false. More info: https://en.cppreference.com/w/cpp/types/void_t
template <typename, typename = std::void_t<>>
struct has_const_iterator: std::false_type { };

template <typename T>
struct has_const_iterator<T, std::void_t<typename T::const_iterator>>
     : std::true_type { };


template <typename T>
inline constexpr bool has_const_iterator_v = has_const_iterator<T>::value;

// has_value_type true if the class has value_type, otherwise is false
template <typename, typename = std::void_t<>>
struct has_value_type : std::false_type { };

template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>>
    : std::true_type { };

template <typename T>
inline constexpr bool has_value_type_v = has_value_type<T>::value;

namespace alp{

template <typename It>
constexpr decltype(auto) select_const_iterator()
{
    if constexpr (has_const_iterator_v<It>)
    return typename It::const_iterator{};

    else if constexpr (std::is_pointer_v<It>){
    using value_type = std::remove_pointer_t<It>;
    using const_pointer = const value_type*;
    return const_pointer{0};
    }
    else if constexpr (has_value_type_v<It>){
    using value_type = typename It::value_type;
        if constexpr (std::is_same_v<typename     std::vector<value_type>::iterator,
                                 It>)
        return typename std::vector<value_type>::const_iterator();
    }
    else 
    static_assert(dependent_false<It>::value, "TODO");

}


template <typename It>
struct iterator_traits{
    using const_iterator = decltype(select_const_iterator<It>());
};


}// namespace



struct A
{ 
    using const_iterator = int;
};

struct B{};


int main()
{
    std::cout << std::boolalpha
    << std::is_same_v<typename alp::iterator_traits<A>::const_iterator, int> 
    << '\n'
    << std::is_same_v<typename alp::iterator_traits<int*>::const_iterator, 
        const int*>
 //    not compile:
 // << std::is_same_v<typename  alp::iterator_traits<B>::const_iterator, const B>
    << '\n';
    using it = std::vector<int>::iterator;
    std::cout << std::is_same_v<alp::iterator_traits<it>::const_iterator, 
    std::vector<int>::const_iterator> 
        << '\n';

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...