c++ - librerias - Preparación para std:: iterator en desuso
vector stl c++ ejemplos (2)
La opción 3 es una versión estrictamente más tipada de la opción 1, ya que debe escribir todos los mismos
typedefs
pero además envolver
iterator_traits<X>
.
La opción 2 es inviable como solución.
Puede deducir algunos tipos (por ejemplo, la
reference
es simplemente
decltype(*it)
), pero no puede deducir
iterator_category
.
No puede diferenciar entre
input_iterator_tag
y
forward_iterator_tag
simplemente por la presencia de operaciones, ya que no puede verificar reflexivamente si el iterador cumple con la garantía multipass.
Además, no se puede distinguir realmente entre esos y
output_iterator_tag
si el iterador produce una referencia mutable.
Tendrán que proporcionarse explícitamente en alguna parte.
Eso deja la Opción 1. Supongo que deberíamos acostumbrarnos a escribir toda la repetitiva. Yo, por mi parte, doy la bienvenida a nuestros nuevos señores del túnel carpiano.
El 21 de marzo, el comité de normas votó para aprobar el desuso de
std::iterator
P0174
propuesto en
P0174
:
La larga secuencia de argumentos nulos es mucho menos clara para el lector que simplemente proporcionar los
typedefs esperados en la propia definición de clase, que es el enfoque adoptado por el borrador de trabajo actual, siguiendo el patrón establecido en c ++ 14
Antes
de la
herencia
c ++ 17
de
std::iterator
se alentaba a eliminar el tedio de la implementación repetitiva del iterador.
Pero la desaprobación requerirá una de estas cosas:
-
Una plantilla repetitiva ahora deberá incluir todos los
typedefs requeridos -
Los algoritmos que funcionan con iteradores ahora necesitarán usar
autolugar de depender del iterador para declarar tipos -
Loki Astari ha sugerido
que
std::iterator_traitspuede actualizarse para que funcione sin heredar destd::iterator
¿Puede alguien aclararme cuál de estas opciones debería esperar, ya que diseño iteradores personalizados con miras a la compatibilidad con c ++ 17 ?
Las alternativas discutidas son claras, pero creo que se necesita un código de ejemplo.
Dado que no habrá un sustituto de idioma y sin depender de boost o de su propia versión de la clase base de iterador, el siguiente código que usa
std::iterator
se fijará en el código debajo.
Con
std::iterator
template<long FROM, long TO>
class Range {
public:
// member typedefs provided through inheriting from std::iterator
class iterator: public std::iterator<
std::forward_iterator_tag, // iterator_category
long, // value_type
long, // difference_type
const long*, // pointer
const long& // reference
>{
long num = FROM;
public:
iterator(long _num = 0) : num(_num) {}
iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
bool operator==(iterator other) const {return num == other.num;}
bool operator!=(iterator other) const {return !(*this == other);}
long operator*() {return num;}
};
iterator begin() {return FROM;}
iterator end() {return TO >= FROM? TO+1 : TO-1;}
};
(Código de std::iterator con permiso original del autor).
Sin
std::iterator
template<long FROM, long TO>
class Range {
public:
class iterator {
long num = FROM;
public:
iterator(long _num = 0) : num(_num) {}
iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
bool operator==(iterator other) const {return num == other.num;}
bool operator!=(iterator other) const {return !(*this == other);}
long operator*() {return num;}
// iterator traits
using difference_type = long;
using value_type = long;
using pointer = const long*;
using reference = const long&;
using iterator_category = std::forward_iterator_tag;
};
iterator begin() {return FROM;}
iterator end() {return TO >= FROM? TO+1 : TO-1;}
};