C++ - Check if all template arguments are power of 2 - templates

I`am trying to find a simple way of checking if parameters passed as template arguments are all power of 2. I found a bithack on the website and I have this:
constexpr bool isPowerOf2(size_t value){
return !(value == 0) && !(value & (value - 1));
}
This works nice for single value but applying this to multiple arguments looks ugly.
static_assert(isPowerOf2(Arg1), "Argument must be a power of 2");
static_assert(isPowerOf2(Arg2), "Argument must be a power of 2");
static_assert(isPowerOf2(Arg3), "Argument must be a power of 2");
It would be better if I could make it look like arePowersOf2(Arg1, Arg2, Arg3), but im not really advanced in template magic. So my question: Is there an easy way of doing it? I would prefer constexpr C++11 solution.

You can write a conjunction trait which checks if all the bools in a parameter pack are true. This example uses #Columbo's bool_pack trick:
template <bool...> struct bool_pack{};
template <bool... bools>
struct conjunction : std::is_same<bool_pack<true, bools...>,
bool_pack<bools..., true>>
{};
template <size_t... Args>
constexpr bool arePowerOf2() {
return conjunction<isPowerOf2(Args)...>::value;
}
Then you would just call it like this:
arePowerOf2<Args...>();
arePowerOf2<Arg1, Arg2, Arg3>();
Live Demo
In C++1z you can use fold expressions for this:
template <size_t... Args>
constexpr bool arePowerOf2() {
return (... && isPowerOf2(Args));
}
C++1z will also get std::conjunction, which is just slightly different from the version above.

A pack of bools is an integer sequence of bools:
template<bool...Bs>using bools = std::integer_sequence<bool, Bs...>;
These help you create a sequence of true, true, true of a specified length:
template<std::size_t...Is>
constexpr bools<(Is,true)...> make_trues_f( std::index_sequence<Is...> ) {
return {};
}
template<std::size_t N>
using make_trues_t = decltype( all_true_f( std::make_index_sequence<N>{} ) );
template<class...Ts>
using make_trues_for_t = make_trues_t<sizeof...(Ts)>;
which gives you:
static_assert(
std::is_same<
bools<isPowerOf2(Args)...>,
make_trues_for_t<Args...>
>::value, "Argument must be a power of 2"
);
or
template<class...Args>
constexpr std::is_same<
bools<isPowerOf2(Args)...>,
make_trues<sizeof...(Args)>
>
all_power_of_2() { return {}; }
Me, I like returning types even from constexpr functions when I know the answer at a type-computation level.
As a bonus, the failed comparison is more clearly what is intended, instead of an off-by-one hack. The is_same compares a sequence of <true, true, false, true> to <true, true, true, true>, as compared to the off-by-one hack which compares <true, true, true, false, true> to <true, true, false, true, true>. In the first case, it is really clear from the type what went wrong -- the false -- especially when you spot that the right hand side is always a pack of only true.

Related

How do I use concepts to constrain the argument types for variadic functions?

I have a variadic function that can take any combination of input arguments, as long as each one of those arguments is convertible to bool:
#include <concepts>
#include <cstddef>
// internal helper functions
namespace {
template <typename T>
constexpr std::size_t count_truths(T t) {
return (bool)t;
}
template <typename T, typename... Args>
constexpr std::size_t count_truths(T t, Args... args) { // recursive variadic function
return count_truths(t) + count_truths(args...);
}
}
template <typename T>
concept Booly = std::convertible_to<T, bool>;
// variadic function for which all arguments should be constrained to Booly<T>
// e.g. only_one(true, false, true, false, true) = false; only_one(true, false) = true
template <typename T, typename... Args> requires Booly<T>
constexpr bool only_one(T t, Args... args) {
return count_truths(t, args...) == 1;
}
I have attempted to constrain the templates using concepts to only allow bool-convertible types to be passed, but I have only managed to do so for the first parameter:
// following lines compile:
only_one(true, false, false);
only_one(BoolConvertible(), true, false);
// this line is correctly forced to failure due to the concept not being satisfied:
only_one(NonBoolConvertible(), false, true);
// BUT this line is not detected as a concept constraint failure (but still compilation failure):
only_one(true, NonBoolConvertible(), false, true);
How can I use C++20 concepts to constrain the remaining template parameters to ensure each one of them in Args... satisfies Booly<> ?
You can expand Args via (Booly<Args> && ...) to pass each indivual type onto Booly. Chaining the result with && will therefore only yield true if all types satisfy Booly.
template <typename T, typename... Args> requires Booly<T> && (Booly<Args> && ...)
constexpr bool only_one(T t, Args... args) {
return count_truths(t, args...) == 1;
}
Demo:
struct foo {
operator bool();
};
struct bar {};
int main() {
only_one(true, true, false);
only_one(foo{}, true);
only_one(bar{}, true); //C2672
only_one(true, bar{}); //C2672
}
You can simply use C++17 fold expression to do this
#include <concepts>
template<std::convertible_to<bool>... Args>
constexpr bool only_one(Args... args) {
return (bool(args) + ... + false) == 1;
}
static_assert(only_one(true, false, true, false, true) == false);
static_assert(only_one(true, false) == true);
static_assert(only_one() == false); // allow empty pack
After following up on a related question after drafting my own, I was inspired by the following answer (https://stackoverflow.com/a/64694337/6177253) to discover an easy solution.
Rather than using requires to constrain on our Booly concept, just use the concept directly when constraining the template parameters:
template <Booly T, Booly... Args>
constexpr bool only_one(T t, Args... args) {
return count_truths(t, args...) == 1;
}
This modification now enforces the constraint on all parameters, at least as far as my own tests can tell.
I leave my question open and this answer here, in case anyone discovers any issues with my approach or potential improvements.

Dynamic Dispatch to Template Function C++

I have a template function (in my case a cuda kernel), where there are a small number of boolean template parameters that can chosen between at runtime. I am happy to instantiate all permutations at compile time and dispatch dynamically, like so (for boolean b0,b1,b2):
if (b0) {
if (b1) {
if (b2) {
myFunc<true,true,true,otherArgs>(args);
} else {
myFunc<true,true,false,otherArgs>(args);
}
} else {
if(b2) {
myFunc<true,false,true,otherArgs>(args);
} else {
myFunc<true,false,false,otherArgs>(args);
}
}
} else {
if(b1) {
if(b2) {
myFunc<false,true,true,otherArgs>(args);
} else {
myFunc<false,true,false,otherArgs>(args);
}
} else {
if(b2) {
myFunc<false,false,true,otherArgs>(args);
} else {
myFunc<false,false,false,otherArgs>(args);
}
}
}
This is annoying to write, and gets exponentially worse if I end up with a b3 and b4.
Is there a simple way to rewrite this in a more concise way in C++11/14 without bringing in large external libraries (like boost)? Something like:
const auto dispatcher = construct_dispatcher<bool, 3>(myFunc);
...
dispatcher(b0,b1,b2,otherArgs,args);
No problem.
template<bool b>
using kbool = std::integral_constant<bool, b>;
template<std::size_t max>
struct dispatch_bools {
template<std::size_t N, class F, class...Bools>
void operator()( std::array<bool, N> const& input, F&& continuation, Bools... )
{
if (input[max-1])
dispatch_bools<max-1>{}( input, continuation, kbool<true>{}, Bools{}... );
else
dispatch_bools<max-1>{}( input, continuation, kbool<false>{}, Bools{}... );
}
};
template<>
struct dispatch_bools<0> {
template<std::size_t N, class F, class...Bools>
void operator()( std::array<bool, N> const& input, F&& continuation, Bools... )
{
continuation( Bools{}... );
}
};
Live example.
So kbool is a variable with represents a compile time constant boolean. dispatch_bools is a helper struct that has an operator().
This operator() takes an array of runtime bools, and starting at max-1 proceeds to spawn max if/else branches, each recursing into call to dispatch_bools with one more compile-time bool calculated.
This generates 2^max code; exactly the code you don't want to write.
The continuation is passed all the way down to the bottom recursion (where max=0). At that point, all of the compile-time bools have been built up -- we call continuation::operator() passing in those compile-time bools as function parameters.
Hopefully continuation::operator() is a template function that can accept compile-time bools. If it is, there are 2^max instantiations of it, each with each of the 2^max possible true/false combinations.
To use this to solve your problem in c++14 you just do:
std::array<bool, 3> bargs={{b0, b1, b2}};
dispatch_bools<3>{}(bargs, [&](auto...Bargs){
myFunc<decltype(Bargs)::value...,otherArgs>(args);
});
This is easy because c++14 has auto lambdas; it can have a template operator() on a lambda. Turning those compile-time bool arguments back into template non-type arguments is easy.
Note that many nominally c++11 compilers support auto-lambdas, because of how easy it was. However, if you lack it, you can still solve this in c++11 with a helper struct:
template<class OtherArgs>
struct callMyFunc {
Args args;
template<class...Bools>
void operator()(Bools...){
myFunc<Bools::value...,otherArgs>(args);
}
};
now use is:
std::array<bool, 3> bargs={{b0, b1, b2}};
dispatch_bools<3>{}(bargs, callMyFunc<otherArgs>{args});
This is basically manually writing what the c++14 lambda would do.
In c++14 you can replace void with auto and return instead of just recursing and it will deduce a return type for you reasonably well.
If you want that feature in c++11 you can either write a lot of decltype code, or you can use this macro:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
and write the body of dispatch_bools like:
template<class T, std::size_t N, class F, class...Bools>
auto operator()( std::array<T, N> const& input, F&& continuation, Bools... )
RETURNS(
(input[max-1])?
dispatch_bools<max-1>{}( input, continutation, kbool<true>{}, Bools{}... )
:
dispatch_bools<max-1>{}( input, continutation, kbool<false>{}, Bools{}... )
)
and similar for the <0> specialization, and get c++14 style return deduction in c++11.
RETURNS makes deducing return types of one-liner functions trivial.
Is there a simple way? No. Can it be done using an unholy mess of garbled templates? Sure, why not.
Implementation
First, this is going to be a bit easier if we have a class rather than a function, simply because parameterized classes can be passed as template parameters. So I'm going to write a trivial wrapper around your myFunc.
template <bool... Acc>
struct MyFuncWrapper {
template <typename T>
void operator()(T&& extra) const {
return myFunc<Acc...>(std::forward<T&&>(extra));
}
};
This is just a class for which MyFuncWrapper<...>()(extra) is equivalent to myFunc<...>(extra).
Now let's make our dispatcher.
template <template <bool...> class Func, typename Args, bool... Acc>
struct Dispatcher {
auto dispatch(Args&& args) const {
return Func<Acc...>()(std::forward<Args&&>(args));
}
template <typename... Bools>
auto dispatch(Args&& args, bool head, Bools... tail) const {
return head ?
Dispatcher<Func, Args, Acc..., true >().dispatch(std::forward<Args&&>(args), tail...) :
Dispatcher<Func, Args, Acc..., false>().dispatch(std::forward<Args&&>(args), tail...);
}
};
Whew, there's quite a bit to explain there. The Dispatcher class has two template arguments and then a variadic list. The first two arguments are simple: the function we want to call (as a class) and the "extra" argument type. The variadic argument will start out empty, and we'll use it as an accumulator during the recursion (similar to an accumulator when you're doing tail call optimization) to accumulate the template Boolean list.
dispatch is just a recursive template function. The base case is when we don't have any arguments left, so we just call the function with the arguments we've accumulated so far. The recursive case involves a conditional, where we accumulate a true if the Boolean is true and a false if it's false.
We can call this with
Dispatcher<MyFuncWrapper, TypeOfExtraArgument>()
.dispatch(extraArgument, true, true, false);
However, this is a bit verbose, so we can write a macro to make it a bit more approachable.1
#define DISPATCH(F, A, ...) Dispatcher<F, decltype(A)>().dispatch(A, __VA_ARGS__);
Now our call is
DISPATCH(MyFuncWrapper, extraArgument, true, true, false);
Complete Runnable Example
Includes a sample myFunc implementation.
#include <utility>
#include <iostream>
#define DISPATCH(F, A, ...) Dispatcher<F, decltype(A)>().dispatch(A, __VA_ARGS__);
template <bool a, bool b, bool c, typename T>
void myFunc(T&& extra) {
std::cout << a << " " << b << " " << c << " " << extra << std::endl;
}
template <bool... Acc>
struct MyFuncWrapper {
template <typename T>
void operator()(T&& extra) const {
return myFunc<Acc...>(std::forward<T&&>(extra));
}
};
template <template <bool...> class Func, typename Args, bool... Acc>
struct Dispatcher {
auto dispatch(Args&& args) const {
return Func<Acc...>()(std::forward<Args&&>(args));
}
template <typename... Bools>
auto dispatch(Args&& args, bool head, Bools... tail) const {
return head ?
Dispatcher<Func, Args, Acc..., true >().dispatch(std::forward<Args&&>(args), tail...) :
Dispatcher<Func, Args, Acc..., false>().dispatch(std::forward<Args&&>(args), tail...);
}
};
int main() {
DISPATCH(MyFuncWrapper, 17, true, true, false);
DISPATCH(MyFuncWrapper, 22, true, false, true);
DISPATCH(MyFuncWrapper, -9, false, false, false);
}
Closing Notes
The implementation provided above will let myFunc return values as well, although your example only included a return type of void, so I'm not sure you'll need this. As written, the implementation requires C++14 for auto return types. If you want to do this under C++11, you can either change all the return types to void (can't return anything from myFunc anymore) or you can try to hack together the return types with decltype. If you want to do this in C++98, ... ... ... ... good luck
1 This macro is susceptible to the comma problem and thus won't work if you pass it zero Booleans. But if you're not going to pass any Booleans, you probably shouldn't be going through this process anyway.

Function with a fixed amount of parameters determined by an integer

I have a class with a template that accepts an integer:
template <unsigned int N>
class Example {};
I'm looking for a way to define a (member)function that accepts some amount of Example objects as arguments. The amount is to be determined by N, so the function would be used like this:
Function(Example<2>(), Example<2>());
Function(Example<3>(), Example<3>(), Example<3>());
What I tried so far:
Using an initializer list, one is able to pass a set of objects to the function:
template <unsigned int N>
void Function(std::initializer_list<Example<N>> list);
//...
Function({Example<2>(), Example<2>()});
However, the problem besides the fact that really only one argument is passed(the list), is that with this method any number of arguments can be used:
Function({Example<2>()});
I also tried using a variadic function:
template <unsigned int N>
void Function(Example<N> e...)
{
va_list args;
va_start(args, e);
//...
}
Function(Example<2>(), Example<2>());
This makes it possible to use real parameters, but the problem of using any number of arguments remains, and it's not possible to know how many arguments were actually passed.
Assuming you want the number of arguments to be deduced from the Example<N> type, and that all Example<I> should share the same such N, a C++17 solution might be
template <unsigned int... I>
auto Function( Example<I>... ) ->
std::enable_if_t<( ( I == sizeof...(I) ) && ... )>
{
// or static_assert() if you always want an error
}
Make Function a variadic template and use std::enable_if_t to constrain your it:
Some IsExample trait can be used to make sure that all arguments are instances of Example
sizeof...(pack) can be used to get the size of the parameter pack
template <unsigned int N, typename... Ts>
auto Function(Ts... xs)
-> std::enable_if_t<(IsExample<Ts>::value && ...)
&& (sizeof...(Ts) == N)>
{
}
live example on wandbox
You should utilize variadic function template with static_assert. Unlike approaches involving enable_if this one will produce a readable error message if incorrect arguments are passed.
template<unsigned int ... I>
void Function(Example<I>... items)
{
static_assert
(
true && (... && (static_cast<unsigned int>(sizeof...(I)) == I))
, "This function accepts N arguments of type Example<N>"
);
}
Online compiler
There are many answers that cover SFINAE friendly based constraints, but I don't like placing my SFINAE in the return value:
template <unsigned int... Is,
std::enable_if_t<( ( Is == sizeof...(Is) ) && ... ), bool> = true
>
void Function( Example<Is>... examples )
{
// code
}
or
template<bool b>
using test_requirement = std::enable_if_t<b, bool>;
template <unsigned int... Is,
test_requirement<( ( Is == sizeof...(Is) ) && ... )> = true
>
void Function( Example<Is>... examples )
{
// code
}
+1 for the Massimiliano Janes's elegant solution.
Unfortunately use folding so works only for C++17.
To test, with C++11/C++14, that all I are equals to sizeof...(I) (and maybe that sizeof...(I) is equal to N, where N is the class template argument), it's enough test that a variadic type, that receive unsigned values, is the same type with a different order of values.
I mean: declaring a trivial struct as
template <std::size_t ... Is>
struct IList;
the test can be
std::is_same<IList<N, sizeof...(Is), Is...>,
IList<sizeof...(Is), Is..., N>>::value
Starting from C++14 it's possible to use std::index_sequence instead of IList.
So Example can be written as
template <unsigned int N>
struct Example
{
template <unsigned int ... Is>
auto Function (Example<Is> ...)
-> typename std::enable_if<
std::is_same<IList<N, sizeof...(Is), Is...>,
IList<sizeof...(Is), Is..., N>>::value>::type
{ /* do something */ }
};
The following is a example of use (but remember to include <type_traits>)
int main()
{
Example<1U> e1;
Example<2U> e2;
// e1.Function(); // error
e1.Function(Example<1>{}); // compile
//e1.Function(Example<1>{}, Example<1>{}); // error
// e2.Function(); // error
//e2.Function(Example<2>{}); // error
e2.Function(Example<2>{}, Example<2>{}); // compile
//e2.Function(Example<2>{}, Example<2>{}, Example<2>{}); // error
}

Distribute argument parameter pack to invoke two functors

I'm trying to invoke two functional objects through one given argument pack (typename Args... args), an integer parameter is provided to mark the border where i need to split the pack to invoke both functional objects correctly.
Consider the following example:
Args... = <int, int, std::vector<int>, std::vector<int>>
unsigned Bounds = 2;
functor Foo (left) and Bar (right)
// Foo is invoked with <int, int>
// Bar is invoked with <std::vector<int>, std::vector<int>>
// An evaluator template class is invoked to merge the result of both,
// for example with an add (operator+) operation
My idea was to create two integer sequences and use std::get to invoke both functional objects at once with those two integer sequences:
// Sequence creator
template<unsigned Position, unsigned Count, unsigned... Pack>
struct make_sequence
: std::conditional<
Count == 0,
std::common_type<sequence<Pack...>>,
make_sequence<Position + 1, Count - 1, Pack..., Position>
>::type { };
// Create a sequence from inclusive from to exclusive to
template<unsigned InclusiveFrom, unsigned ExclusiveTo>
using make_sequence_from_to_t = typename make_sequence<
InclusiveFrom,
(ExclusiveTo <= InclusiveFrom) ? 0U : (ExclusiveTo - InclusiveFrom)
>::type;
template<typename LeftType, typename RightType, unsigned Bounds, typename Evaluator>
class distribute_functor
{
LeftType left_;
RightType right_;
template<unsigned... LeftSeq, unsigned... RightSeq, typename... Args>
auto internal_invoke(sequence<LeftSeq...>, sequence<RightSeq...>, Args... args)
{
return Evaluator::evaluate(left_(std::get<LeftSeq>(args)...),
// ~~~~~~~~~~~~~~~^^^^^^^~~^^^^~~~~~
// error C3528: 'LeftSeq': the number of
// elements in this pack expansion does not
// match the number of elements in 'args'
right_(std::get<RightSeq>(args)...));
}
public:
template<typename Left, typename Right>
distribute_functor(Left left, Right right)
: left_(std::forward<Left>(left)), right_(std::forward<Right>(right)) { }
template<typename... Args>
auto operator() (Args... args)
{
return internal_invoke(make_sequence_from_to_t<0, Bounds>{},
make_sequence_from_to_t<Bounds, sizeof...(Args)>{},
std::forward<Args>(args)...);
}
};
However the VisualStudio 14 compiler complains about a mismatch between the count of parameters in the arguments pack and in the sequence:
error C3528: 'LeftSeq': the number of elements in this pack expansion does not match the number of elements in 'args'
There is still the way to use std::tuple for the functor invocation which i don't prefer.
Is there another or better way to partial invoke two functional objects in one step from one argument pack?
std::get cannot be used this way.
You should write internal_invoke like this:
template<unsigned... LeftSeq, unsigned... RightSeq, typename ArgsAsTuple>
auto internal_invoke(sequence<LeftSeq...>, sequence<RightSeq...>,ArgsAsTuple&& args) const
{
return Evaluator::evaluate(left_(std::get<LeftSeq>(args)...),
right_(std::get<RightSeq>(args)...));
}
And invoke it with forward_as_tuple:
return internal_invoke(make_sequence_from_to_t<0, Bounds>{},
make_sequence_from_to_t<Bounds, sizeof...(Args)>{},
std::forward_as_tuple(args...));
Explanation:
Two paramter packs of different arity must be expanded separately. When you write std::get<LeftSeq>(args)..., you try to expand together packs of different arity. This cannot be done. You should have wrote std::get<LeftSeq>(args... /* 1st expand/) ... /* 2nd expand */. This is syntactically correct but does not match std::get API. std::forward_as_tuple is there to help you and has been written precisely for those types of use cases.
Edit:
If you want to avoid the tuple, then you must write your own version of std::get to match your need, provided you expand the parameters correctly as I explained above.

C++0x type inference messes with boost::enable_if

I'm trying to write a generic filtering function that performs linear interpolation at a given sampling coordinate in an multi-dimensional array (arbitrary rank). For this, I need a recursive function template that walks through all dimensions of an array until it hits a value and its associated type. I use boost::enable_if in order to detect when to stop iterating through the dimensions. It works ok until I try to "percolate" the return value/type to the topmost function. For this purpose, I attempted to use C++0x type inference but it doesn't seem to mix well with boost::enable_if.
I isolated the problem down to what follows:
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I == 0), typename T::value_type >::type
{
return t[0];
}
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type
{
return test< typename T::value_type, std::size_t(I - 1) >(t[0]);
}
The compiler (GCC 4.6) complains with the following code:
typedef std::array< std::array< float, 1 >, 1 > myarray;
myarray ma;
std::cout << typeid (test< myarray, 1 >(ma)).name() << std::endl;
Error message:
error: conversion from 'boost::enable_if_c<true, float>::type' to non-scalar type 'boost::enable_if_c<true, std::array<float, 1u> >::type' requested
It seems that decltype uses the return value from test< T, I > even though it is instructed to use that of test< T, I - 1 >. Any idea why this behavior occurs? For now, it think I'll just turn the whole thing into a functor...
The issue is that you passed a T() (and T) to decltype. The types aren't folding down. This is clearly revealed if you compare the return expression to what you passed to decltype- they're inconsistent.
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type
{
return test< typename T::value_type, std::size_t(I - 1) >(t[0]);
}
decltype: test<T
return expression: test< typename T::value_type
When defining forward functions like this, the decltype-expression used to define the return type should nearly always be exactly the same as the actual return expression.
Edit: I need to add that you should not pass rvalues when in reality you will pass lvalues, especially to templates, as you may well end up with different results.