¿Por qué no se pueden usar los rangos para la funcionalidad de la biblioteca de tuberías?

10

Jonathan Boccara (autor de Fluent C ++ ) escribió una biblioteca llamada tuberías .

Esta "tubería", dice la página principal del repositorio, no es como el uso de rangos, a pesar de que se ve igual: no se basa en tirones perezosos, sino en empujones ansiosos. Pero se afirma que no se puede usar la biblioteca de rangos para realizar varias operaciones 'pipe'. Por ejemplo:

  • descomprimir: tome una entrada comprimida, un rango de k-tuplas esencialmente, y produzca k salidas separadas e independientes.
  • fork - Produce múltiples copias (independientes) de un contenedor / rango.

No entiendo por qué, en principio, ese es el caso. (Por supuesto, con la excepción de los rangos donde no puede obtener el iterador / centinela final).

einpoklum
fuente

Respuestas:

7

Lo que se está discutiendo es esencialmente la diferencia entre una metodología de procesamiento basada en inserción y una basada en extracción. En un sistema de inserción como esta biblioteca de tuberías, se establece una cadena de procesamiento, y cada paso de procesamiento empuja sus datos directamente al siguiente. En un sistema de extracción como rangos, establece una representación de datos, a la que puede acceder y modificar según sea necesario. El procesamiento no ocurre por sí solo; sucede solo cuando alguien intenta consumir el rango.

Las operaciones unzipy forkson operaciones de uno a muchos: toman una sola entrada y la asignan a muchas operaciones de procesamiento.

Como sistema de inserción, la biblioteca de tuberías puede manejar operaciones de uno a muchos debido a la estructura de su API. Una operación está representada por una llamada de función; la entrada está implícita en el punto de uso (usarla >>=o pasarla a un procesador). Los parámetros de la función definen su salida (ignorando los parámetros destinados al propio procesador). Y dado que las funciones de C ++ pueden tener números arbitrarios de parámetros, una operación de mapeo de uno a muchos naturalmente se cae. Simplemente suministre procesadores apropiados para las distintas salidas.

Como sistema de extracción, los rangos se basan en valores de retorno. C ++ no tiene un mecanismo de lenguaje para devolver múltiples valores, por lo que lo mejor que podemos hacer es devolver un "valor" que represente múltiples valores.

Sin embargo, el encadenamiento del adaptador de rango se basa en última instancia en que las entradas son rangos . Y un "'valor' que representa múltiples valores" en sí mismo no es un rango. Puede contener rangos, pero eso no lo convierte en un rango.

Así que ahora tiene que tomar este tipo definitivamente "no de rango" y hacer que todos sus adaptadores de rango trabajen con él. La aplicación de un adaptador de rango debe transmitir esa operación a través del tipo, creando una operación de muchos a muchos. Hacer eso no es fácil.

Pero lo más importante ... eso probablemente no sea lo que quieres . Si tiene forkun rango, entonces seguramente querrá hacer un procesamiento diferente en los rangos replicados. Y eso cierra completamente cualquier posibilidad de usar la |operación para hacer eso. Tendrá que crear formas de aplicar adaptadores a partes específicas de estas tuplas de rango. Y esas formas se verán cada vez más como un procesador basado en inserción.

Al final del día, un sistema de estilo pull solo tiene una salida en cada nivel. Eso es solo parte del concepto central de dicha API: cada paso de procesamiento genera un rango. Esto tiene sus ventajas (procesamiento diferido) pero la representación de operaciones uno a muchos es una de sus áreas débiles.

Los rangos ciertamente pueden tener una unzipfunción (en forkrealidad solo está copiando el rango). Pero no sería un |adaptador de estilo; sería una función que toma un rango sobre algún tipo descomponible y devuelve una tupla de rangos. Si desea realizar un mayor procesamiento con ellos, deberá almacenar la tupla en un valor, acceder a los elementos individuales y usarlos como mejor le parezca.

Nicol Bolas
fuente