c++ c++11 stl predicate

c++ - ¿Qué significa "Los predicados no deberían modificar su estado debido a una llamada de función"?



c++11 stl (4)

Además de las otras respuestas, muchos de los algoritmos que toman predicados no prometen ningún orden transversal particular (las sobrecargas de ExecutionPolicy permiten el recorrido intercalado). Es posible que obtenga diferentes respuestas a la misma pregunta.

Si hay varios subprocesos que llaman al predicado 1 y cambia algún valor compartido, es una carrera de datos , es decir, un comportamiento indefinido.

  1. o un hilo intercalando llamadas a

Estaba leyendo en línea sobre C ++ y me encontré con esta declaración:

Los predicados no deben modificar su estado debido a una llamada de función.

No entendí qué significa "estado" aquí. ¿Puede alguien por favor elaborar con un ejemplo?


Consideremos el algoritmo std::count_if como ejemplo. Atraviesa un rango y cuenta con qué frecuencia un predicado determinado se evalúa como verdadero. Además, supongamos que queremos verificar cuántos elementos en un contenedor son más pequeños que un número dado, por ejemplo, 5 o 15.

Un predicado puede ser muchas cosas. Solo tiene que ser invocable. Puede ser un functor:

struct check_if_smaller { int x; bool operator()(int y) { return y < x; } };

Puede crear diferentes instancias de ese predicado, por ejemplo, estos dos

check_if_smaller a{5}; check_if_smaller b{15};

se puede usar para verificar si los números son menores que 5 o 15 respectivamente:

bool test1 = a(3); // true because 3 < 5 bool test2 = b(20); // false because 20 is not < 15

El miembro x es el estado del predicado. Normalmente, esto no debería cambiar cuando se aplica el predicado (llamando a su operator() ).

De wikipedia :

En lógica matemática, un predicado se entiende comúnmente como una función de valor booleano P: X → {verdadero, falso}, llamado predicado en X. Sin embargo, los predicados tienen muchos usos e interpretaciones diferentes en matemáticas y lógica, y su definición precisa , el significado y el uso variarán de una teoría a otra.

Hablando descuidadamente, un predicado es una función que asigna algo a un booleano. El hecho de que usemos un functor que no es solo una función, sino un objeto de función con un estado puede considerarse como un detalle de implementación, y comúnmente se espera que la evaluación repetida del mismo predicado para la misma entrada produzca el mismo resultado. Además, los algoritmos hacen esta suposición y nada realmente les impide copiar el predicado que pasa. Si la evaluación del predicado alteraría su estado interno, el algoritmo podría no funcionar como se esperaba.


En términos simples, un estado en un predicado es un miembro de datos. Un predicado que cambia el estado significa que el miembro se cambia durante la ejecución del algoritmo y ese cambio afectará el comportamiento del predicado.

La razón para evitar esto es el hecho de que los algoritmos no están obligados a mantener una sola instancia de un predicado. Se pueden copiar fácilmente, y el estado cambiado en una copia, no se compartirá con un estado en otra copia. Como resultado, el programa se comportará inesperadamente (para alguien que espera que el cambio de estado entre en vigencia).


Esencialmente, qué estándar dice que el predicado debe actuar como una función pura (en términos matemáticos), es decir, su valor de retorno debe depender solo de la entrada.

La mención de estado porque los predicados pueden copiarse o invocarse en diferentes subprocesos, lo que depende de la implementación y el comportamiento de la plataforma. Para lambda y otros objetos invocables que no son funciones, esto puede significar acceso desordenado al almacenamiento, capturado por referencia o acceder a valores diferentes si fueron capturados por valor. Para una función, significa que cualquier efecto secundario (incluido el cambio de variables estáticas) puede ocasionar problemas.

Si un predicado para ordenar devolvería resultados diferentes para el mismo par, entonces algunos algoritmos de ordenamiento se volverán inválidos.