std::conjunction
| Definido en el archivo de encabezado <type_traits>
|
||
template<class... B> struct conjunction; |
(desde C++17) | |
Forma la conjunción lógica de los rasgos de tipo B..., efectivamente llevando a cabo un AND lógico en la secuencia de rasgos.
La especialización std::conjunction<B1, ..., BN> tiene una base pública e inequívoca que es
- si
sizeof...(B) == 0,std::true_type; de lo contrario, - el primer tipo
BienB1, ..., BNpara el quebool(Bi::value) == false, oBNsi no existe tal tipo.
Los nombres de los miembros de la clase base, excepto conjunction y operator=, no están ocultos y están inequivocadamente disponibles en conjunction.
La conjunción es de cortocircuito: si hay un argumento de plantilla de tipo Bi con bool(Bi::value) == false, entonces instanciar conjunction<B1, ..., BN>::value no requiere la instanciación de Bj::value para j > i.
El comportamiento de un programa que añade especializaciones para conjunction o conjunction_v no está definido.
Parámetros de plantilla
| B... | - | Todo argumento de plantilla Bi para el que Bi::value se instancia debe ser utilizable como una clase base y definir el miembro value, que es convertible a bool.
|
Plantilla de variable auxiliar
<tbody> </tbody> template<class... B> inline constexpr bool conjunction_v = conjunction<B...>::value; |
(desde C++17) | |
Posible implementación
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
|
Notas
Una especialización de conjunction no necesariamente hereda de std::true_type o de std::false_type: simplemente hereda de la primera B cuyo miembro ::value, explícitamente convertido a bool, es false, o de la última B cuando todos pueden convertirse a true. Por ejemplo, std::conjunction<std::integral_constant<int, 2>, std::integral_constant<int, 4>>::value es 4.
La instanciación de cortocircuito diferencia a conjunction de las expresiones de pliegue: una expresión de pliegue como (... && Bs::value) instancia toda B en Bs, mientras que std::conjunction_v<Bs...> detiene la instanciación una vez que el valor puede determinarse. Esto es particularmente útil si el tipo posterior es costoso de instanciar o puede causar un error grave cuando se instancia con el tipo incorrecto.
Ejemplo
#include <iostream>
#include <type_traits>
// func se habilita si todas las Ts... tienen el mismo tipo que T
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...) {
std::cout << "todos los tipos en el paquete son T\n";
}
// de lo contrario
template<typename T, typename... Ts>
std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...) {
std::cout << "no todos los tipos en el paquete son T\n";
}
int main() {
func(1, 2, 3);
func(1, 2, "hola!");
}
Salida:
todos los tipos en el paquete son T
no todos los tipos en el paquete son T
Véase también
(C++17) |
Metafunción NOT lógico. (plantilla de clase) |
(C++17) |
Metafunción variádica de OR lógico. (plantilla de clase) |