web-dev-qa-db-fra.com

Y a-t-il une raison d'utiliser std :: conjonction / std :: disjunction au lieu d'une expression de repli sur "&&" / "||"?

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.

23
rubenvb

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 avec bool(Bi::value) == false, l'instanciation de conjunction<B1, ..., BN>::value Ne nécessite pas l'instanciation de Bj::value Pour j > i.

27
Vittorio Romeo