C ++ 20 tiene un mecanismo para decidir cuándo una entidad restringida particular está "más restringida" que otra. Esto no es una cosa simple.
Esto comienza con el concepto de dividir una restricción en sus componentes atómicos, un proceso llamado normalización de restricción . Es grande y demasiado complejo entrar aquí, pero la idea básica es que cada expresión en una restricción se desglosa en sus piezas conceptuales atómicas, recursivamente, hasta llegar a una sub-expresión componente que no es un concepto.
Por lo tanto, veamos cómo se definen los conceptos integral
y :signed_integral
template<class T>
concept integral = is_integral_v<T>;
template<class T>
concept signed_integral = integral<T> && is_signed_v<T>;
La descomposición de integral
es justa is_integral_v
. La descomposición de signed_integral
es is_integral_v && is_signed_v
.
Ahora, llegamos al concepto de subsunción de restricción . Es un poco complicado, pero la idea básica es que se dice que una restricción C1 "subsume" una restricción C2 si la descomposición de C1 contiene todas las subexpresiones en C2. Podemos ver que integral
no subsume signed_integral
, pero signed_integral
lo hace subsume integral
, ya que contiene todo lo que integral
hace.
A continuación, llegamos a ordenar entidades restringidas:
Una declaración D1 está al menos tan restringida como una declaración D2 si * D1 y D2 son declaraciones restringidas y las restricciones asociadas a D1 subsumen las de D2; o * D2 no tiene restricciones asociadas.
Como signed_integral
subsumes integral
, el <signed_integral> wrapper
es "al menos tan restringido" como el <integral> wrapper
. Sin embargo, lo contrario no es cierto, debido a que la subsunción no es reversible.
Por lo tanto, de acuerdo con la regla para entidades "más restringidas":
Una declaración D1 está más restringida que otra declaración D2 cuando D1 está al menos tan restringido como D2, y D2 no está al menos tan restringido como D1.
Como <integral> wrapper
no está al menos tan restringido como <signed_integral> wrapper
, este último se considera más restringido que el primero.
Y por lo tanto, cuando los dos podrían postularse, gana la declaración más restringida.
Tenga en cuenta que las reglas de subsunción de restricción se detienen cuando se encuentra una expresión que no es a concept
. Entonces, si hiciste esto:
template<typename T>
constexpr bool my_is_integral_v = std::is_integral_v<T>;
template<typename T>
concept my_signed_integral = my_is_integral_v<T> && std::is_signed_v<T>;
En este caso, my_signed_integral
no subsumiría std::integral
. Aunque my_is_integral_v
se define de manera idéntica std::is_integral_v
, porque no es un concepto, las reglas de subsunción de C ++ no pueden analizarlo para determinar si son lo mismo.
Por lo tanto, las reglas de subsunción lo alientan a construir conceptos a partir de operaciones sobre conceptos atómicos.