Is there a reason to use std::conjunction/std::disjunction instead of a fold expression over “&&”/“||”?

风流意气都作罢 提交于 2021-02-05 19:58:17

问题


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 with bool(Bi::value) == false, then instantiating conjunction<B1, ..., BN>::value does not require the instantiation of Bj::value for j > i.



来源:https://stackoverflow.com/questions/55161235/is-there-a-reason-to-use-stdconjunction-stddisjunction-instead-of-a-fold-exp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!