2

I'm writing a container view parameterized by an iterator, and I need to know what const_iterator's type is. Something like this:

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 = ???
};

How can I know the type of const_iterator from iterator?


Edit: A way to convert an iterator to const_iterator is with this code:

// 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';

}
Antonio
  • 579
  • 1
  • 3
  • 12
  • 4
    Why would container view be parameterized by iterator instead of container itself? – user7860670 Mar 23 '19 at 15:55
  • If you look at [this similar question](https://stackoverflow.com/questions/7759246/c-iterator-to-const-iterator), it's very easy if you know the type of the container. I think `template class Container_view` is the way to go here. – alter_igel Mar 23 '19 at 16:01
  • I prefer to use an iterator because I'm working with matrixes. If I use an iterator the implementation of a submatrix, a matrix_view, and a submatrix_view are all the same class. How do you implement a submatrix and a matrix_view with the same code if you use Container as a parameter? – Antonio Mar 23 '19 at 16:43
  • 2
    The short answer is - what you are asking for is not possible. An `iterator` only provides info about itself. It doesn't provide any info about other iterator types, or about the container it comes from. Only the container knows what types are used for its `iterator` and `const_iterator`. So you need access to the container in your view class. – Remy Lebeau Mar 23 '19 at 18:04

0 Answers0