Я пишу контейнерное представление, параметризованное итератором, и мне нужно знать тип 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';
}