问题
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.
回答1:
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
Bi
withbool(Bi::value) == false
, then instantiatingconjunction<B1, ..., BN>::value
does not require the instantiation ofBj::value
forj > i
.
来源:https://stackoverflow.com/questions/55161235/is-there-a-reason-to-use-stdconjunction-stddisjunction-instead-of-a-fold-exp