Y a-t-il des cas spécifiques que vous ne pouvez pas faire correctement avec std::conjunction
/std::disjunction
et ne pas utiliser l'expression plus "fondamentale" (c'est-à-dire la fonction de langue au lieu de la fonction de bibliothèque) replier l'expression sur &&
/||
?
Exemple:
// 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
}
contre
// 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
}
La version utilisant une expression de pli est plus brève et généralement plus lisible (bien que les opinions puissent différer à ce sujet). Je ne vois donc pas pourquoi il a été ajouté à la bibliothèque avec les expressions de repli.
std::conjunction
Court-circuite l'instanciation ::value
, Contrairement à l'expression de repli. Cela signifie que, étant donné:
template <typename T>
struct valid_except_void : std::false_type { };
template <>
struct valid_except_void<void> { };
Les éléments suivants seront compilés:
template <typename... Ts>
constexpr auto test = std::conjunction_v<valid_except_void<Ts>...>;
constexpr auto inst = test<int, void>;
Mais ce qui suit ne le fera pas:
template <typename... Ts>
constexpr auto test = (valid_except_void<Ts>::value && ...);
constexpr auto inst = test<int, void>;
exemple en direct sur godbolt.org
De cppreference :
La conjonction est un court-circuit: s'il existe un argument de type de modèle
Bi
avecbool(Bi::value) == false
, l'instanciation deconjunction<B1, ..., BN>::value
Ne nécessite pas l'instanciation deBj::value
Pourj > i
.