Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variadic and_/or_ [Feature Request] #251

Open
Alexhuszagh opened this issue Jul 5, 2017 · 7 comments
Open

Variadic and_/or_ [Feature Request] #251

Alexhuszagh opened this issue Jul 5, 2017 · 7 comments

Comments

@Alexhuszagh
Copy link
Contributor

Alexhuszagh commented Jul 5, 2017

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.

@edouarda
Copy link
Owner

edouarda commented Jul 5, 2017

This looks interesting, if you do a pull request we will have a look at it. Any other comment?

@Alexhuszagh
Copy link
Contributor Author

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.

@odinthenerd
Copy link
Contributor

could be made much more efficient using a recursive alias and fast tracking, you could even theoretically backfill since there is an identity value

@odinthenerd
Copy link
Contributor

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...>;

@odinthenerd
Copy link
Contributor

@Alexhuszagh more thorough explanation of back filling and recursive aliases here http://odinthenerd.blogspot.de/2017/03/backfilled-join-why-kvasir-mpl-is.html

@odinthenerd
Copy link
Contributor

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.

@Alexhuszagh
Copy link
Contributor Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants