c++ - example - ¿Puede queue:: pop devolver un valor ahora?
queue c++ implementation (3)
No hay muchos casos en los que std::move()
pueda incluirse en la biblioteca estándar, pero hay casos. Por ejemplo, si el contenedor usa un asignador con estado, sus hijos también usan este asignador, pero no se moverá a un resultado: esto preferiría obtener una versión construida predeterminada de un asignador (si lo elimino correctamente). Dado que los asignadores tienen estado, esto significa que el objeto no se puede mover y, por lo tanto, la construcción del movimiento falla con una excepción. ¿Por qué este tipo tiene un constructor de movimiento? Bueno, porque podría crearse una instancia con un asignador sin estado, en cuyo caso el movimiento no se lanzará. Además, una vez que pasamos a las clases definidas por el usuario, no tenemos idea de en qué condiciones podría moverlas.
Sé que std::queue::pop()
devuelve void
. Por dos razones:
- Excepción de seguridad: algo podría tirar después de quitar el elemento.
- Para poder devolver el valor por referencia.
Multa.
Ahora, si entiendo el nuevo C ++ 11 mover la semántica correctamente, el segundo ya no es un argumento válido.
Entonces ... ¿lo único que impide que std::queue
tenga una función de tipo pop
que devuelva el valor radica en la posibilidad de que el constructor de movimientos lance?
Me cuesta mucho pensar en situaciones en las que un constructor de este tipo lanzaría. ¿Quién sabe de un ejemplo?
Creo que lo mismo ocurre con std::stack::pop()
, std::vector::pop_front()
, std::vector::pop_back()
, std::deque::pop_front()
, std::deque::pop_back()
, std::list::pop_front()
, std::list::pop_back()
y lo que no.
Otro problema es que no todas las clases se benefician realmente del movimiento, es decir, es posible que solo tengan un ctor de copia.
struct DontLikeMoves{
// some data, whatever...
DontLikeMoves(DontLikeMoves const& other){
// might throw, who knows!
// and this will even get called for rvalues
}
};
Usando técnicas inteligentes de SFINAE, de hecho sería posible tener un pop_and_move () no lanzador atómico solo para tipos de datos que implementan movimientos de no lanzar o copias de no lanzar.
Incluso hay una construcción noexcept () disponible para ver si algo puede lanzar.
Uno de los nuevos conceptos en C ++ 11 en particular que extiende SFINAE es que si el cuerpo no compila, la función no existe. Por lo tanto uno podría implementar basado en noexcept ().
Yo diría que, para la compatibilidad con versiones anteriores, la función necesitaría un nuevo nombre, que por lo tanto le permite coexistir con la funcionalidad existente de llamarlos por separado, sin romper contenedores de tipos que no tienen la semántica para permitirlo.