home | help
std::conjunction(3)	       C++ Standard Libary	     std::conjunction(3)

NAME
     std::conjunction - std::conjunction

Synopsis
	Defined in header <type_traits>
	template< class... B >		 (since C++17)
	struct conjunction;

	Forms  the logical conjunction of the type traits B..., effectively per-
     forming a
	logical AND on the sequence of traits.

	The specialization std::conjunction<B1, ..., BN> has a public and  unam-
     biguous base
	that is

	  * if sizeof...(B) == 0, std::true_type; otherwise
	  * the first type Bi in B1, ..., BN for which bool(Bi::value) == false,
     or BN if
	    there is no such type.

	The  member  names  of the base class, other than conjunction and opera-
     tor=, are not
	hidden and are unambiguously available in conjunction.

	Conjunction is short-circuiting: if there is a template type argument Bi
     with
	bool(Bi::value)  ==  false,  then  instantiating  conjunction<B1,   ...,
     BN>::value does
	not require the instantiation of Bj::value for j > i.

	If  the  program  adds specializations for std::conjunction or std::con-
     junction_v, the
	behavior is undefined.

Template parameters
	B... - every template argument Bi for which  Bi::value	is  instantiated
     must be usable
	       as  a  base  class and define member value that is convertible to
     bool

	Helper variable template

	template< class... B >						  (since
     C++17)
	inline constexpr bool conjunction_v = conjunction<B...>::value;

Possible implementation
	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> {};

Notes
	A specialization of conjunction does not necessarily inherit from either
	std::true_type	or  std::false_type: it simply inherits from the first B
     whose
	::value, explicitly converted to bool, is false, or from the very last B
     when all of
	them convert to true. For  example,  std::conjunction<std::integral_con-
     stant<int, 2>,
	std::integral_constant<int, 4>>::value is 4.

	The short-circuit instantiation differentiates conjunction from fold ex-
     pressions: a
	fold  expression,  like  (... && Bs::value), instantiates every B in Bs,
     while
	std::conjunction_v<Bs...> stops instantiation once the value can be  de-
     termined. This
	is  particularly useful if the later type is expensive to instantiate or
     can cause a
	hard error when instantiated with the wrong type.

	   Feature-test macro	  Value    Std		   Feature
	__cpp_lib_logical_traits 201510L (C++17) Logical operator type traits

Example
     // Run this code

      #include <iostream>
      #include <type_traits>

      // func is enabled if all Ts... have the same type as T
      template<typename T, typename... Ts>
      std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>>
      func(T, Ts...)
      {
	  std::cout << "all types in pack are T\n";
      }

      // otherwise
      template<typename T, typename... Ts>
      std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>>
      func(T, Ts...)
      {
	  std::cout << "not all types in pack are T\n";
      }

      template<typename T, typename... Ts>
      constexpr  bool  all_types_are_same  =  std::conjunction_v<std::is_same<T,
     Ts>...>;

      static_assert(all_types_are_same<int, int, int>);
      static_assert(not all_types_are_same<int, int&, int>);

      int main()
      {
	  func(1, 2, 3);
	  func(1, 2, "hello!");
      }

Output:
      all types in pack are T
      not all types in pack are T

See also
	negation    logical NOT metafunction
	(C++17)     (class template)
	disjunction variadic logical OR metafunction
	(C++17)     (class template)

http://cppreference.com 	   2024.06.10		     std::conjunction(3)

home | help