отсутствуют ссылки на признаки распределителя c и const_reference и преобразование итератора в постоянный итератор

#c #containers #c 17 #typetraits #const-iterator

#c #контейнеры #c 17 #признаки типов #const-итератор

Вопрос:

Я пытаюсь реализовать пользовательский класс контейнера, совместимый с std, с помощью итератора.
Для этого я начал определять определения общедоступных типов, которые будут использоваться признаками как для класса контейнера, так и для итератора.
Я хочу сделать его совместимым с c 17 и стараться не использовать удаленные функции c 20 или устаревший c 17.
Это то, что я получил:

 template <typename T, typename Alloc = std::allocator<T>>
class container {
    using allocator_type = Alloc;
    using value_type = std::allocator_traits<Alloc>::value_type;
    using pointer = std::allocator_traits<Alloc>::pointer;
    using const_pointer = std::allocator_traits<Alloc>::const_pointer;
    using reference = value_typeamp;; // <-- here 
    using const_reference = const value_typeamp;; // <-- here 
    using difference_type = std::allocator_traits<Alloc>::difference_type;
    using size_type = std::allocator_traits<Alloc>::size_type;

    class iterator;
};

template <typename T, typename Alloc = std::allocator<T>>
class container::iterator {
    using value_type = std::allocator_traits<Alloc>::value_type;
    using pointer = std::allocator_traits<Alloc>::pointer;
    using const_pointer = std::allocator_traits<Alloc>::const_pointer;
    using reference = value_typeamp;; // <-- here 
    using const_reference = const value_typeamp;; // <-- here
    using difference_type = std::allocator_traits<Alloc>::difference_type;
    using size_type = std::allocator_traits<Alloc>::size_type;
};
  

Должен ли я сам определять типы ссылок и const_reference, как я делал в примере, или есть другой стандартный способ сделать это?
Другой вопрос заключается в том, как определить const_iterator без дублирования моего итератора.
Некоторые говорят, что я должен шаблонировать свой итератор с типом значения, некоторые просто пишут новый итератор.
Если бы я использовал шаблон, я не знаю, как бы я создал для него правильные черты типа, поэтому мои определения функций для std:
reference operator*() const и pointer operator->() const ,
потому reference что было бы const_reference и const_reference было бы технически const const_reference .
Например:

 template <typename T>
class container {
    
    template <typename ValueType>
    class iterator;

    using iterator = iterator<T>;
    using const_iterator = iterator<const T>;
};

template <typename ValueType>
class container::iterator {
public:
    using value_type = ValueType;
    using pointer = value_type*;
    using const_pointer = const value_type*;
    using reference = value_typeamp;;
    using const_reference = const value_typeamp;;

    reference operator*() const;
    pointer operator->() const;
};
  

Комментарии:

1. Не могли бы вы уточнить. ваш вопрос немного о заработной плате

2. Что вы подразумеваете под «я должен шаблонировать свой итератор»?

3. Кстати, не должно value_type быть просто T ?

4. Да, это будет, но в примерах, которые я нашел в сети, а также в реализациях boost использовались allocator_traits, поэтому я подумал, что, возможно, это полезно для чего-то …, я мог бы определить все типы только с помощью T

Ответ №1:

Должен ли я сам определять типы ссылок и const_reference, как я делал в примере

ДА. Распределитель не знает, как реализован ваш контейнер, поэтому он не может знать, как определить эти псевдонимы типов.

Другой вопрос заключается в том, как определить const_iterator без дублирования моего итератора.

С помощью магии шаблонов. iterator<T> против iterator<const T> .

поскольку ссылка будет const_reference, а const_reference будет технически const const_reference

Это не проблема, если это связано с тем, что const_reference const Tamp; из-за правил свертки const const const_reference это просто const Tamp; то, что вы хотели бы.

Комментарии:

1. определение типов const_pointer в шаблоне итератора приведет к: const const T* . Это действительно?

2. @Lessi если псевдоним типа X = const T , то const X просто const T и допустимо.