C++ Variadic template AND and OR

巧了我就是萌 提交于 2019-12-04 22:21:00

问题


Can you use C++11 variadic templates to complete /* ??? */ in:

template<bool...v> struct var_and { static bool constexpr value = /* ??? */; };

so that var_and<v...>::value provides && over the boolean pack v at compile-time?

Can you do the same for struct var_or<v...> for ||?

Can you use short-circuit evaluation (in both cases)?

Edit: An update to the accepted answer added that C++17 fold expressions enable

template<bool... v> constexpr bool var_and = (v && ...);
template<bool... v> constexpr bool var_or  = (v || ...);

It seems that, for parameter pack-based approaches, only a restricted type of "short-circuit evaluation" is possible: while instantiating var_or<true,foo(),bar()> only calls || once, it also calls both foo and bar.


回答1:


You don't want value to be a typedef.

template<bool head, bool... tail>
struct var_and {
    static constexpr bool value = head && var_and<tail...>::value;
};

template<bool b> struct var_and<b> {
    static constexpr bool value = b;
};

Obviously the same can be done for ||.

Short circuit evaluation doesn't matter because this only deals with constant expressions which won't have any side effects.

Here's another method which stops recursively generating types as soon as it find a false value, emulating a kind of short circuiting:

template<bool head, bool... tail>
struct var_and { static constexpr bool value = false; };

template<bool... tail> struct var_and<true,tail...> {
    static constexpr bool value = var_and<tail...>::value;
};

template<> struct var_and<true> {
    static constexpr bool value = true;
};

Update for C++17: Using a fold expression makes this much simpler.

template<bool...v> struct var_and {
    static constexpr bool value = (v && ...);
};

Or also using a template variable as enobayram suggests:

template<bool... b> constexpr bool var_and = (b && ...);



回答2:


I just needed something similar, but I have the luxury of using C++14, so I've ended up going with the following, which is probably faster (to compile) than the accepted answer:

template <size_t N>
constexpr bool and_all(const bool (&bs) [N]) {
  for(bool b: bs) if(!b) return false;
  return true;
}

Now, this is constexpr, so it can be used in compile time contexts as well as runtime. So we can, for instance, use it in a context like some_struct<and_all({true, false, arg_pack...})>



来源:https://stackoverflow.com/questions/11892759/c-variadic-template-and-and-or

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