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
typedef
s 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
typedef
s requeridos -
Los algoritmos que funcionan con iteradores ahora necesitarán usar
auto
lugar de depender del iterador para declarar tipos -
Loki Astari ha sugerido
que
std::iterator_traits
puede 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;}
};