Is there any specific cases you cannot correctly do with std::conjunction/std::disjunction and not using the more "fundamental" (i.e. language feature instead of library feature) fold expression over &&/||?
Example:
// func is enabled if all Ts... have the same type template<typename T, typename... Ts> std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...> > func(T, Ts...) { // TODO something to show } vs
// func is enabled if all Ts... have the same type template<typename T, typename... Ts> std::enable_if_t<(std::is_same<T, Ts> &&...)> func(T, Ts...) { // TODO something to show } The version using a fold expression is more brief and generally more readable (although opinions might differ on that). So I don't see why it was added to the library together with fold expressions.
std::conjunction short-circuits ::value instantiation, while the fold expression doesn't. This means that, given:
template <typename T> struct valid_except_void : std::false_type { }; template <> struct valid_except_void<void> { }; The following will compile:
template <typename... Ts> constexpr auto test = std::conjunction_v<valid_except_void<Ts>...>; constexpr auto inst = test<int, void>; But the following won't:
template <typename... Ts> constexpr auto test = (valid_except_void<Ts>::value && ...); constexpr auto inst = test<int, void>; live example on godbolt.org
From cppreference:
Conjunction is short-circuiting: if there is a template type argument
Biwithbool(Bi::value) == false, then instantiatingconjunction<B1, ..., BN>::valuedoes not require the instantiation ofBj::valueforj > i.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With