¿Dónde puedo encontrar todas las garantías de excepción para los contenedores y algoritmos estándar?

Sí, he mirado el estándares C++ que pude encontrar (o los borradores), pero no encuentro ninguna garantía de excepción completa dada por los contenedores STL. Todo lo que puedo encontrar son secciones ocasionales con descripciones incompletas en algo de las funciones para algo de los tipos O tal vez está ahí pero no lo encuentro, no lo sé.

Nota: estoy no pidiendo una lista de todas las garantías que la gente pueda pensar, que es básicamente en esta pregunta.
Estoy buscando el fuente autorizada de esta información en sí, o preferiblemente, una versión gratuita de la fuente (por ejemplo, un borrador de la norma) donde puedo tratar más o menos como oficial.

preguntado el 28 de julio de 12 a las 08:07

@bames53: ¿Ejemplo? "vector::swap garantiza una fuerte seguridad de excepción si el tipo subyacente es móvil; de lo contrario, garantiza la seguridad de excepción básica". No pude encontrar esto en el enlace estándar que puse aquí. -

Tampoco veo esa garantía en el estándar. ¿Qué te hace pensar que eso está garantizado? No creo que lo sea, y si el tipo de elemento es móvil parece irrelevante para vector::swap porque se requiere que vector::swap funcione en tiempo constante, lo que significa que, en general, no puede hacer un intercambio de elementos. -

@bames53: Mi error, eso fue un error tipográfico, quise decir vector::insert (Cual podría utilizan el std::swap debajo). De todos modos, no dije que esté garantizado, solo di un ejemplo potencial de algo que estaba buscando. -

@bames53: ¿En serio? Es un poco trivial... asigne un nuevo contenedor, copie los nuevos datos (destruya las copias si hay un error), luego mueva los datos antiguos. Funciona; es posible que sea lento, y me gustaría saber si esto está garantizado. Si no, entonces no lo es. Pero como dije: acabo de dar un ejemplo potencial... si ya supiera la respuesta, ¡no necesitaría buscarla! -

@bames53: Lo que me impulsó a escribir esta pregunta fue que solo pude encontrar el associative.reqmts.except y unord.req.except secciones en el estándar para responderme, que estaban muy incompletas por sí mismas. Ni siquiera soñé que el .modifiers La sección, por ejemplo, contendría información de requisitos de excepción. Entonces sí, ahora que las respuestas a continuación están aquí, puedo ver que mucha de la información está allí, pero cuando publiqué esto no pude encontrarla. -

3 Respuestas

Leer el estándar puede dar miedo (volvamos al estándar), pero Bjarne Stroustrup ha escrito un apéndice muy bueno sobre este tema en su libro 'El lenguaje de programación C++'. Publicó este apéndice en

http://www.stroustrup.com/3rd_safe0.html , a http://www.stroustrup.com/3rd_safe.pdf

Es bastante largo y detallado (y bien escrito). Por ejemplo, puede encontrar interesante la sección E.4, cite:

E.4 Garantías de contenedores estándar

Si una operación de biblioteca genera una excepción, puede asegurarse de que los objetos en los que opera se dejen en un estado bien definido, y lo hace. Por ejemplo, at() lanza out_of_range para un vector (§16.3.3) no es un problema con la seguridad de excepción para el vector. El escritor de at() no tiene problemas para asegurarse de que un vector esté en un estado bien definido antes de lanzarlo.

Además, el apartado E.4.1 establece

Además de la garantía básica, la biblioteca estándar ofrece una fuerte garantía para algunas operaciones que insertan o eliminan elementos.

echa un vistazo a la página 956. Contiene una tabla de garantías para varias operaciones para vector, deque, list y map. En resumen, todas las operaciones en esos contenedores son fuertes o no arrojables, a excepción de N - elemento insertado en el mapa que ofrece las garantías básicas.

Nota: el texto anterior es antiguo y no aborda C++ 11, pero debería ser lo suficientemente correcto para la mayoría de los objetivos y propósitos.

Cuando se trata de C++ 11...

la norma establece primero, sobre los contenedores array, deque, forward_list, list, vector, map, set, unordered_map, unordered_set, queue,stack: en

23.2.1/10:

A menos que se especifique lo contrario (ver 23.2.4.1, 23.2.5.1, 23.3.3.4 y 23.3.6.5), todos los tipos de contenedores definidos en esta Cláusula cumplen con los siguientes requisitos adicionales:

— si una función insert() o emplace() lanza una excepción al insertar un solo elemento, esa función no tiene efectos.
— si una función push_back() o push_front() lanza una excepción, esa función no tiene efectos.
— ninguna función erase(), clear(), pop_back() o pop_front() genera una excepción.
— ningún constructor de copia u operador de asignación de un iterador devuelto genera una excepción.
- ninguna función swap () lanza una excepción.
— ninguna función swap() invalida cualquier referencia, puntero o iterador que haga referencia a los elementos de los contenedores que se intercambian.

Las peculiaridades señaladas en las secciones respectivas mencionadas anteriormente (cada una denominada Garantías de seguridad de excepción) se refieren principalmente a casos especiales contra la pared, como cuando se trata de excepciones del hash de los tipos contenidos, operaciones de comparación, así como intercambio de lanzamiento y movimiento de lanzamiento. operaciones.

respondido 12 mar '15, 18:03

Ah, no me di cuenta al principio, pero el PDF parece tener la información que necesito (aunque todavía tengo que verificarlo)... no contiene información de C++11 pero sigue siendo útil. :) Gracias. +1 - user541686

Eso no parece que tenga todo lo que necesito... por ejemplo, ¿qué pasa con std::rotate? Es como std::copy? ¿O es más fuerte o más débil? (Me doy cuenta de que esto puede ser diferente en C ++ 11 que en C ++ 03 y versiones anteriores: podría usar cualquier combinación de constructores de copia, constructores de movimiento, asignaciones de copia, asignaciones de movimiento e intercambios, dependiendo de cómo se implemente. I' Necesito saber en qué tipo de garantías puedo confiar, tanto para C ++ 11 como para C ++ 03 eventualmente, pero antes de C ++ 11 también es un buen comienzo). user541686

Para los algoritmos no está tan claro. Le sugiero que haga una lista de los métodos que le interesan y haga una nueva pregunta titulada 'seguridad de excepción de los algoritmos estándar'. Los algoritmos funcionan mediante intercambio, inserción, etc., por lo que no pueden funcionar mejor que los contenedores subyacentes, pero debe leer en cada uno de los estándares cuáles son los requisitos. Por ejemplo, para rotar, los elementos del contenedor deben ser intercambiables, etc. No hay una declaración explícita (hasta donde puedo encontrar) sobre la garantía en caso de que el intercambio se produzca en medio de una acción de rotación. Lo leí como 'débil', pero intente hacer una nueva pregunta. - johan lundberg

De acuerdo, supongo que seguiré con lo que veo en mi implementación STL actual con respecto a lo que no esté presente en el apéndice, y basaré las garantías en eso... Haré más preguntas más adelante si es necesario. ¡Ese PDF es genial! - user541686

n3376

23.2.1 Requisitos generales del contenedor [container.requirements.general]

10 el párrafo

A menos que se especifique lo contrario (ver 23.2.4.1, 23.2.5.1, 23.3.3.4 y 23.3.6.5), todos los tipos de contenedores definidos en esta Cláusula cumplen los siguientes requisitos adicionales:
— si una función insert() o emplace() lanza una excepción al insertar un solo elemento, esa función no tiene efectos.
- si una función push_back () o push_front () lanza una excepción, esa función no tiene ningún efecto.
- ninguna función erase (), clear (), pop_back () o pop_front () arroja una excepción.
- ningún constructor de copia u operador de asignación de un iterador devuelto arroja una excepción.
- ninguna función swap () lanza una excepción.
— ninguna función swap() invalida cualquier referencia, puntero o iterador que haga referencia a los elementos de los contenedores que se intercambian.
[Nota: el iterador end() no hace referencia a ningún elemento, por lo que puede invalidarse. —nota al final]

23.2.4 Contenedores asociativos [asociative.reqmts]

23.2.4.1 Garantías de seguridad de excepción [asociative.reqmts.except]

1 Para contenedores asociativos, ninguna función clear() lanza una excepción. erase(k) no lanza una excepción a menos que esa excepción sea lanzada por el objeto Compare del contenedor (si lo hay).
2 Para contenedores asociativos, si cualquier operación lanza una excepción dentro de una función insert o emplace que inserta un solo elemento, la inserción no tiene efecto.
3 Para contenedores asociativos, ninguna función de intercambio lanza una excepción a menos que esa excepción sea lanzada por el intercambio del objeto Comparar del contenedor (si lo hay).

23.2.5 Contenedores asociativos desordenados [unord.req]

23.2.5.1 Garantías de seguridad de excepción [unord.req.except]

1 Para contenedores asociativos no ordenados, ninguna función clear() lanza una excepción. erase(k) no lanza una excepción a menos que esa excepción sea lanzada por el objeto Hash o Pred del contenedor (si lo hay).
2 Para contenedores asociativos no ordenados, si se lanza una excepción por cualquier operación que no sea la función hash del contenedor desde dentro de una función insert o emplace que inserta un solo elemento, la inserción no tiene efecto.
3 Para contenedores asociativos desordenados, ninguna función de intercambio genera una excepción a menos que esa excepción sea generada por el intercambio del objeto Hash o Pred del contenedor (si lo hay).
4 Para contenedores asociativos no ordenados, si se lanza una excepción desde dentro de una función rehash() que no sea la función hash o la función de comparación del contenedor, la función rehash() no tiene efecto.

23.3.3.4 modificadores deque [deque.modifiers]

void push_back(T&&x); Párrafo 2

Observaciones: Si se lanza una excepción que no sea el constructor de copia, el constructor de movimiento, el operador de asignación o el operador de asignación de movimiento de T, no hay efectos. Si el constructor de movimiento de un T que no es CopyInsertable lanza una excepción, los efectos no se especifican.

borrado del iterador (const_iterator primero, const_iterator último); Párrafo 6

Lanza: nada a menos que el constructor de copia, el constructor de movimiento, el operador de asignación o el operador de asignación de movimiento de T generen una excepción.

23.3.6.5 modificadores de vectores [vector.modifiers]

void push_back(T&&x); Párrafo 2

Si el constructor de movimiento de un T que no es CopyInsertable lanza una excepción, los efectos no se especifican.

borrado del iterador (const_iterator primero, const_iterator último); Párrafo 5

Lanza: nada a menos que el constructor de copia, el constructor de movimiento, el operador de asignación o el operador de asignación de movimiento de T generen una excepción.

Respondido el 20 de junio de 20 a las 10:06

Hmm... entonces, por ejemplo, si llamo vector::insert() para insertar 2 elementos dentro de un vector de 10000 elementos en el índice 9998, y el constructor de copia del objeto podría arrojar, entonces, ¿el vector tomará todos los 10000 elementos y los copiará en algún lugar, para garantizar la seguridad? - user541686

@Mehrdad: Te perdiste esto while inserting a **single element** - martín york

Uh, no, precisamente por eso te pregunté. Si estuviera insertando un solo elemento, la respuesta ya estaría en su publicación. Estaba buscando algo completo, que explicara lo que sucede, por ejemplo, en algo como el escenario anterior. - user541686

23.2.1 párrafo 10: if an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects. - martín york

@Mehrdad: Pareces estar malinterpretando mi respuesta. No hay garantía para 2 (aparte del básico). Proporciona una garantía sólo cuando while inserting a **single element**. - martín york

El documento al que se ha vinculado, el borrador del estándar n3337, puede tratarse como oficial. Es el estándar C++ 11 más cambios editoriales menores.

Solo necesita aprender a leer el estándar, lo cual es comprensible porque no pretende ser fácil de leer.

Para encontrar las garantías de excepción para cualquier operación de biblioteca en particular, verifique la especificación de esa operación para obtener comentarios y observaciones sobre las excepciones. Si la función es una función miembro, verifique la especificación del tipo para obtener comentarios sobre la seguridad de excepción y qué requisitos cumple. Luego verifique los requisitos cumplidos para las garantías de excepción que deben realizar los objetos para cumplir con esos requisitos.

Para los tipos y algoritmos genéricos, también verifique los requisitos establecidos en los parámetros de la plantilla para ver qué requisitos deben cumplir esos tipos para que se cumplan todas las garantías de excepción hechas por el tipo o el algoritmo o la función miembro (si los parámetros de la plantilla no Si cumple con los requisitos especificados, el uso de la plantilla con esos parámetros tiene un comportamiento indefinido y no se aplica ninguna de las especificaciones de la plantilla).

Respondido 28 Jul 12, 21:07

¿Sabes lo que quieren decir con "modificadores"? Me desconcertó por completo cuando vi garantías de excepción allí... - user541686

@Mehrdad El estándar divide las funciones miembro para cada clase en varias categorías. Si observa la descripción general de la clase, verá una lista de todas las funciones divididas en categorías. Cada grupo tiene un enlace al principio que lo llevará a la sección que especifica las funciones en ese grupo. - bames53

@Mehrdad Por ejemplo, la sección 23.3.6.0 tiene la descripción general de la plantilla de clase vectorial y si se desplaza hacia abajo verá un comentario "//23.3.6.3 capacidadseguido de funciones relacionadas con el tamaño y la capacidad del vector. Si sigue el enlace a la sección 23.3.6.3, encontrará las especificaciones para cada una de las funciones en ese grupo, incluida la información sobre cualquier excepción que garantice una función. por ejemplo para vector::reserve() se especifica que "Si se lanza una excepción que no sea el constructor de movimiento de un tipo que no sea CopyInsertable, no hay efectos". - bames53

@Mehrdad En otras palabras, la sección 'modificadores' significa 'funciones que el estándar ha categorizado como modificadores'. No tiene nada que ver específicamente con las excepciones, y también encontrará información sobre excepciones en los otros grupos, como "constructores, copia y asignación", "capacidad", "datos", "algoritmos especializados", etc. - bames53

OH... ¿entonces por "modificadores" solo quieren decir mutadores? Eso tiene mucho sentido (aparte de cómo resize y at no son modificadores)... ¡Guau, qué desajuste de impedancia! ¡Gracias por la explicación detallada! - user541686

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.