Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 一种将迭代器转换为常量迭代器的方法_C++_Iterator - Fatal编程技术网

C++ 一种将迭代器转换为常量迭代器的方法

C++ 一种将迭代器转换为常量迭代器的方法,c++,iterator,C++,Iterator,我正在编写一个由迭代器参数化的容器视图,我需要知道常量迭代器的类型是什么。大概是这样的: template <typename It> // It = random access iterator class Container_view{ using value_type = typename std::iterator_traits<It>::value_type; using reference = ... ... using i

我正在编写一个由迭代器参数化的容器视图,我需要知道常量迭代器的类型是什么。大概是这样的:

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

为什么容器视图要由迭代器而不是容器本身来参数化呢?如果您了解容器的类型,就很容易了。我认为
template class Container\u view
是一种方法。我更喜欢使用迭代器,因为我使用的是矩阵。如果我使用迭代器,子矩阵、矩阵视图和子矩阵视图的实现都是同一个类。如果您使用容器作为参数,如何使用相同的代码实现子矩阵和矩阵视图?简单的回答是-您所要求的是不可能的。
迭代器
只提供有关自身的信息。它不提供关于其他迭代器类型或它来自的容器的任何信息。只有容器知道它的
迭代器和
常量迭代器使用的类型。因此,您需要访问视图类中的容器。
// 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';

}