teclado superindice subindices subindice quimica power poner matematicas con como c++ c++11 iterator operator-overloading initializer-list

c++ - subindices - superindice 2



¿Por qué `std:: initializer_list` no proporciona un operador de subíndice? (2)

De hecho, es un poco molesto, no tener operador de corchetes para std :: initializer_list, ya que la necesidad de acceso directo aleatorio para un índice específico es un escenario razonable.

Sin embargo, esta habilidad se puede agregar con un código simple:

// the class _init_list_with_square_brackets provides [] for initializer_list template<class T> struct _init_list_with_square_brackets { const std::initializer_list<T>& list; _init_list_with_square_brackets(const std::initializer_list<T>& _list): list(_list) {} T operator[](unsigned int index) { return *(list.begin() + index); } }; // a function, with the short name _ (underscore) for creating // the _init_list_with_square_brackets out of a "regular" std::initializer_list template<class T> _init_list_with_square_brackets<T> _(const std::initializer_list<T>& list) { return _init_list_with_square_brackets<T>(list); }

Ahora tenemos una nueva función global llamada _ (guión bajo) que probablemente no sea un buen nombre para un método global de C ++, a menos que queramos crear una lib de utilidad "similar a una digitación" para C ++, que tendrá su propio espacio de nombres, sobrecargando el _ función para todo tipo de otros usos útiles.

La nueva función _ se puede usar ahora así:

void f(std::initializer_list<int> list) { cout << _(list)[2]; // subscript-like syntax for std::initializer_list! } int main() { f({1,2,3}); // prints: 3 cout << _({1,2,3})[2]; // works also, prints: 3 return 0; }

Debe tenerse en cuenta que la solución proporcionada anteriormente no es una buena oferta en términos de rendimiento si ejecuta muchos elementos de std :: initializer_list, ya que un objeto temporal del tipo sugerido arriba _init_list_with_square_brackets se crea repetidamente. Lo cual nuevamente plantea la pregunta de por qué esto no fue provisto por el estándar en sí mismo.

Supongamos que está escribiendo una función que acepta una list llamada std::initializer_list y que la función requiere acceso aleatorio a los elementos de la list . Sería conveniente escribir la list[i] lugar de list.begin()[i] . Entonces, ¿por qué std::initializer_list proporciona una definición de operator[] ?

No puedo pensar en ningún caso donde un operator[] regresa const T& no esté bien definido. La eficiencia no parece ser el problema aquí, ya que std::initializer_list<T>::iterator tiene un alias para const T* , que es claramente un iterador de acceso aleatorio.


Según Bjarne Stroustrup en la Sección 17.3.4.2 (página 497) de The C ++ Programming Language, 4th Edition:

Desafortunadamente, initializer_list no proporciona subíndices.

No se da más razón.

Creo que es una de estas razones:

  1. es una omisión, o
  2. debido a que la clase initializer_list se implementa con una matriz y usted tendría que verificar los límites para proporcionar un acceso seguro, podría usarse más fácilmente de forma insegura si se proporcionara esa interfaz, o
  3. ser coherente con el paradigma de iteración de algoritmos estándar, o
  4. porque initializer_lists son, por su naturaleza, ad-hoc, hay más margen de error al abordarlas directamente

2 y 4 suenan débiles. como lo hace 3. Mi dinero está en 1.