是否有理由在“&&”/“||”上使用 std::conjunction/std::disjunction 而不是折叠表达式?
Is there a reason to use std::conjunction/std::disjunction instead of a fold expression over "&&"/"||"?
是否有任何特定情况你不能正确地使用 std::conjunction
/std::disjunction
而不是使用 more "fundamental" (即语言功能而不是库功能)折叠表达式 &&
/||
?
示例:
// 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
}
对
// 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
}
使用折叠表达式的版本更简洁,通常更易读(尽管对此意见可能不同)。所以我不明白为什么它和折叠表达式一起被添加到库中。
std::conjunction
短路 ::value
实例化,而折叠表达式则不会。这意味着,给定:
template <typename T>
struct valid_except_void : std::false_type { };
template <>
struct valid_except_void<void> { };
以下将编译:
template <typename... Ts>
constexpr auto test = std::conjunction_v<valid_except_void<Ts>...>;
constexpr auto inst = test<int, void>;
但以下不会:
template <typename... Ts>
constexpr auto test = (valid_except_void<Ts>::value && ...);
constexpr auto inst = test<int, void>;
来自 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
.
是否有任何特定情况你不能正确地使用 std::conjunction
/std::disjunction
而不是使用 more "fundamental" (即语言功能而不是库功能)折叠表达式 &&
/||
?
示例:
// 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
}
对
// 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
}
使用折叠表达式的版本更简洁,通常更易读(尽管对此意见可能不同)。所以我不明白为什么它和折叠表达式一起被添加到库中。
std::conjunction
短路 ::value
实例化,而折叠表达式则不会。这意味着,给定:
template <typename T>
struct valid_except_void : std::false_type { };
template <>
struct valid_except_void<void> { };
以下将编译:
template <typename... Ts>
constexpr auto test = std::conjunction_v<valid_except_void<Ts>...>;
constexpr auto inst = test<int, void>;
但以下不会:
template <typename... Ts>
constexpr auto test = (valid_except_void<Ts>::value && ...);
constexpr auto inst = test<int, void>;
来自 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
.