#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
и допустимо.