◐ Shell
clean mode source ↗

std::conjunction - cppreference.com

De cppreference.com

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 Bi en B1, ..., BN para el que bool(Bi::value) == false, o BN si 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

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