Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Variadic template AND and OR

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.

like image 348
nknight Avatar asked Aug 09 '12 22:08

nknight


People also ask

What is a variadic template C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.

What is a variadic function in C?

Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.

How do you access Variadic arguments?

To access variadic arguments, we must include the <stdarg. h> header.

What is Pack expansion?

Pack expansion A pattern followed by an ellipsis, in which the name of at least one parameter pack appears at least once, is expanded into zero or more comma-separated instantiations of the pattern, where the name of the parameter pack is replaced by each of the elements from the pack, in order. template<class...


1 Answers

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 && ...);
like image 171
bames53 Avatar answered Sep 19 '22 06:09

bames53