edouarda/brigand

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.