Variadic and_/or_ [Feature Request]
Alexhuszagh opened this issue · 7 comments
While porting boost::mpl code to Brigand, I noticed that although and_
and or_
exist, they only support 2 arguments.
It's fairly easy to versions taking a variadic parameter pack, using template specialization, without adding much code bloat.
And
template<typename... Ts>
struct and_;
template<>
struct and_<>: true_type {};
template<typename T, typename... Ts>
struct and_<T, Ts...> : brigand::integral_constant < typename T::value_type, T::value && and_<Ts...>::value > {};
Or
template<typename... Ts>
struct or_;
template<>
struct or_<> : brigand::integral_constant < bool, false > {};
template <typename T, typename... Ts>
struct or_<T, Ts...> : brigand::integral_constant < typename T::value_type, T::value || or_<Ts...>::value > {};
If there's any interest, I can make a pull request. Thanks for the excellent library.
This looks interesting, if you do a pull request we will have a look at it. Any other comment?
This probably isn't the most efficient algorithm, since I believe it will automatically make N
comparisons when it could short-circuit, but it's clean and idiomatic. It could likely be optimized later.
could be made much more efficient using a recursive alias and fast tracking, you could even theoretically backfill since there is an identity value
template<unsigned N>
struct or_impl;
template<>
struct or_impl<0>;
{
template<typename T0=bool_<false>, typename T1 = bool_<false> (something liek 6 more here)>
using f = bool_<T0::value || (rest here)>;
}
template<>
struct or_impl<1>;
{
template<typename T0=bool_<false>, typename T1 = bool_<false> (many more here)>
using f = bool_<T0::value || (rest here)>;
}
template<typename...Ts>
using or_ = typename or_imple<(figure out based on sizeof...(Ts))>::template f<Ts...>;
@Alexhuszagh more thorough explanation of back filling and recursive aliases here http://odinthenerd.blogspot.de/2017/03/backfilled-join-why-kvasir-mpl-is.html
essentially the algorithms any and all are variadic and_ and or_ operations if you use identity as a predicate. In kvasir::mpl all and any are implemented in terms of find_if in order to allow short circuiting which is actually quite fast. One could also implement and_ and or_ in terms of find_if as well.
@odinthenerd I'll read through your blog thoroughly tonight (and others) since I'm less familiar with highly efficient TMP and therefore back-filling and recursive aliases, and then update my PR accordingly.
Thanks for the immensely helpful comments.