Triggering void constexpr at compile time? - c++

I have a constexpr function that groups many static_asserts for design contracts. I would like to call it at compile time, without having to create an unused constexpr variable.
Here is an example of what I currently have to do (c++17).
template<size_t N = 0, typename... Ts, typename F>
inline constexpr int tuple_for(const std::tuple<Ts...>& t, const F& func) {
func(std::get<N>(t));
if constexpr(N < sizeof...(Ts) - 1) {
return tuple_for<N + 1, Ts...>(t, func);
} else {
return 0;
}
}
auto do_checks = [](const auto& t) {
static_assert(has_some_method_v<decltype(t)>,
"You need some_method");
return 0;
}
[[maybe_unused]]
constexpr int i_am_sad = tuple_for(my_tuple, do_checks);
Is there any other way to achieve this behaviour? Maybe something new in c++17?
Thank you.
edit:
Note that as these checks are to be generalized, I believe having the asserts in a function is the right way to go here.

You might use it in other constexpr context as static_assert:
static_assert((static_cast<void>(tuple_for(my_tuple, do_checks)), true), "!");
[Note]: the cast to void is to generalize, if you want to return class with evil overloaded comma.

static_assert is a declaration-statement, so you can just plonk it in free space.
No need for a function.
This is precisely the use case for that. :)

Related

How do I unwrap a parameter pack of length 1 (containing a single value)?

I am writing a little variadic summing function (using c++20, but my question would remain the same with c++17 syntax). I would like to make the following code as short and clear as possible (but without using folding expressions. This is only a toy problem, but in later applications I would like to avoid fold expressions):
Additive auto sum(Additive auto&& val, Additive auto&&... vals) {
auto add = [](Additive auto&& val1, Additive auto&& val2) {
return val1 + val2;
}; // neccessary??
if constexpr(sizeof...(vals) == 1) {
return add(val, std::forward<decltype(vals)>(vals)...); // (1)
//return val + std::forward<decltype(vals)>(vals)...; // (2)
}
else return val + sum(std::forward<decltype(vals)>(vals)...);
}
Using line (1) the above code compiles, but it makes the definition of the 'add' lambda neccessary. Line (2), however, does not compile, I get the following error with gcc: parameter packs not expanded with ‘...’. If I add parentheses around the std::forward expression in line (2), I get the following error: expected binary operator before ‘)’ token.
Is there any way to pass a parameter pack with length 1 to an operator?
Embrace the power of negative thinking and start induction with zero instead of one:
auto sum(auto &&val, auto &&...vals) {
if constexpr (sizeof...(vals) == 0)
return val;
else
return val + sum(std::forward<decltype(vals)>(vals)...);
}
The above definition has the side effect that sum(x) will now compile and return x. (In fact, you can even make the function work with no arguments, by having it return zero, but then the question arises: zero of which type? To avoid having to go there, I left this case undefined.) If you insist on sum being defined only from arity 2 upwards, you can use this instead:
auto sum(auto &&val0, auto &&val1, auto &&...vals) {
if constexpr (sizeof...(vals) == 0)
return val0 + val1;
else
return val0 + sum(std::forward<decltype(val1)>(val1),
std::forward<decltype(vals)>(vals)...);
}
However, you should probably allow the ‘vacuous’ case whenever it makes sense to do so: it makes for simpler and more general code. Notice for example how in the latter definition the addition operator appears twice: this is effectively duplicating the folding logic between the two cases (in this case it’s just one addition, so it’s relatively simple, but with more complicated operations it might be more burdensome), whereas handling the degenerate case is usually trivial and doesn’t duplicate anything.
(I omitted concept annotations, as they do not seem particularly relevant to the main problem.)
template<class... Additive> decltype(auto) sum(Additive &&...val) {
return (std::forward<Additive>(val) + ...);
}
?
Offtopic: unsure about Op's real needs, I've accidentally quickdesigned one thing I've been thinking of, from time to time. :D
#include <iostream>
#include <functional>
#include <type_traits>
template<class... Fs> struct Overloads;
template<class F, class... Fs> struct Overloads<F, Fs...>: Overloads<Fs...> {
using Fallback = Overloads<Fs...>;
constexpr Overloads(F &&f, Fs &&...fs): Fallback(std::forward<Fs>(fs)...), f(std::forward<F>(f)) {}
template<class... Args> constexpr decltype(auto) operator()(Args &&...args) const {
if constexpr(std::is_invocable_v<F, Args...>) return std::invoke(f, std::forward<Args>(args)...);
else return Fallback::operator()(std::forward<Args>(args)...);
}
private:
F f;
};
template<class... Fs> Overloads(Fs &&...fs) -> Overloads<Fs...>;
template<class F> struct Overloads<F> {
constexpr Overloads(F &&f): f(std::forward<F>(f)) {}
template<class... Args> constexpr decltype(auto) operator()(Args &&...args) const {
return std::invoke(f, std::forward<Args>(args)...);
}
private:
F f;
};
template<> struct Overloads<> {
template<class... Args> constexpr void operator()(Args &&...) const noexcept {}
};
constexpr int f(int x, int y) noexcept { return x + y; }
void g(int x) { std::cout << x << '\n'; }
template<class... Vals> decltype(auto) omg(Vals &&...vals) {
static constexpr auto fg = Overloads(f, g);
return fg(std::forward<Vals>(vals)...);
}
int main() {
omg(omg(40, 2));
}
>_<
You can unpack the one item into a variable and use that:
if constexpr (sizeof...(vals) == 1) {
auto&& only_value(std::forward<decltype(vals)>(vals)...);
return val + only_value;
}

Mimic std::bind_front in c++17 for calling member functions

Is it somehow possible to easily mimic std::bind_front in C++17 ? (just for member function wrapping is fine)
I took a look at implementation in c++20 aiming to copy but it seems its very much implementation specific indeed.
I'm thinking a lambda wrapper or template function/object might work?
(Performance is not an issue here)
This can be a starting point
template<typename F, typename ...FrontArgs>
struct bindfronthelper
{
bindfronthelper(F f, FrontArgs&&...args)
: mF{std::move(f)}
, mFrontArg{std::forward<FrontArgs>(args)...}
{}
template<typename ...BackArgs>
auto operator()(BackArgs&&...args) const
{
return std::apply(mF, std::tuple_cat(mFrontArg, std::forward_as_tuple(args...)));
}
F mF;
std::tuple<std::decay_t<FrontArgs>...> mFrontArg;
};
template<typename F, typename ...FrontArgs>
auto mybindfront(F f, FrontArgs&&...args)
{
return bindfronthelper<F, FrontArgs...>{std::move(f), std::forward<FrontArgs>(args)...};
}
https://godbolt.org/z/Tz9fen
Written quickly and not tested well, so there might be some pitfalls in corner cases. At least it shows how this can be achieved.
Ok I made this over complicated, here is simpler version:
template<typename T, typename ...Args>
auto tuple_append(T&& t, Args&&...args)
{
return std::tuple_cat(
std::forward<T>(t),
std::forward_as_tuple(args...)
);
}
template<typename F, typename ...FrontArgs>
decltype(auto) mybindfront(F&& f, FrontArgs&&...frontArgs)
{
return [f=std::forward<F>(f),
frontArgs = std::make_tuple(std::forward<FrontArgs>(frontArgs)...)]
(auto&&...backArgs)
{
return std::apply(
f,
tuple_append(
frontArgs,
std::forward<decltype(backArgs)>(backArgs)...));
};
}
https://godbolt.org/z/cqPjTY
still passes all test I've provided. I'm keeping old version since with a bit of work it can be tweaked to work with older standard of c++.
One really simpel way I found is with lambda's (in this case capturing this - but you can change that easily to be generally adoptable):
auto bind_m = [this](auto mem_f) {
auto wrapper = [=] (auto&&... args) {return std::mem_fn(mem_f)(this, std::forward<decltype(args)>(args)...);};
return wrapper;
};
The lambda creates another lambda and returns it.
template<typename F, typename... FRONT_ARGS>
auto bind_front(F&& f, FRONT_ARGS&&... front_args)
{
// front_args are copied because multiple invocations of this closure are possible
return [captured_f = std::forward<F>(f), front_args...](auto&&... back_args) {
return std::invoke(captured_f, front_args...,
std::forward<decltype(back_args)>(back_args)...);
};
}

Get Last element of parameter pack in C++17 / C++20

I would like to get the last element of a parameter pack. I did it with the following code GodBolt:
template<typename... Args>
auto last(Args&&... args){
const auto& last = (args, ...);
return last;
}
But now I get the warning
left operand of comma operator has no effect
But this is exactly what I wanted to achieve... Is there a way to make it clear.
In general I like to get warnings for unused values so I don't want to disable all of them (-Wno-unused-value).
In addition I could do it with a recursive template, but a fold expression seems to be better here.
Wrapping args in any function call would remove the warning.
You could make an identity function specifically for this purpose, but you might as well use std::forward and get proper forwarding as a bonus.
template<typename... Args>
decltype(auto) last(Args&&... args){
return (std::forward<Args>(args), ...);
}
Make a tuple and get the last element:
template<typename... Args>
auto last(Args&&... args)
{
return std::get<sizeof...(Args)-1>(std::forward_as_tuple(args...));
}
Test:
int main()
{
auto&& last_element = last(1, 1.0, true);
static_assert(std::is_same_v<bool, std::remove_cvref_t<decltype(last_element)>>);
}
Demo
C++11 Friendly Demo
As suggested by HolyBlackCat the easiest way to remove this warning is to use an "identity / dummy-function" like this:
template<typename T>
constexpr inline decltype(auto) identityFkt(T&& t)
{
return std::forward<T>(t);
}
It can be used this way:
const auto& last = (identityFkt(std::forward<AParamPack>(aParamPack)), ...);
It results in the same assembly (checked # godbolt) - no overhead (with -O3).
Thank you: #HolyBlackCat
You can use another implementation (it's less efficient, but compiler should be able remove inefficiency here)
template <class T>
decltype(auto) last(T && ... t) { return t; }
template <class ... TT,class T>
decltype(auto) last(T &&,TT && ... tt) { return last( std::forward<TT>(tt)... ); }

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.

Execute integer templated function based on run-time parameter

I often have some prototype behaviour that generates output based on some design method. I template the design method, which enables a lot of functionality I need. However, sometimes the design method is given at runtime, so I'm usually required to write a huge switch statement. It usually looks like this:
enum class Operation
{
A, B
};
template<Operation O>
void execute();
template<>
void execute<A>()
{
// ...
}
template<>
void execute<B>()
{
// ...
}
void execute(Operation o)
{
switch (o)
{
case Operation::A: return execute<Operation::A>();
case Operation::B: return execute<Operation::B>();
}
}
I'm curious as to whether anyone has figured out a nice pattern for this system - the main drawbacks of this method is that one has to type out all the supported enumerations and do maintenance several places if new enumerations are implemented.
e: I should add that the reasons for messing with compile-time templates is to allow the compiler to inline methods in HPC as well as inherit constexpr properties.
e2: in effect, I guess what I'm asking is to have the compiler generate all the possible code paths using an implicit switch structure. Perhaps some recursive template magic?
If you really want to utilize templates for this task you can use technique similar to this one.
// Here second template argument default to the first enum value
template<Operation o, Operation currentOp = Operation::A>
// We use SFINAE here. If o is not equal to currentOp compiler will ignore this function.
auto execute() -> std::enable_if<o == currentOp, void>::type
{
execute<currentOp>();
}
// Again, SFINAE technique. Compiler will stop search if the template above has been instantiated and will ignore this one. But in other case this template will be used and it will try to call next handler.
template<Operation o, Operation currentOp = Operation::A>
void execute()
{
return execute<o, static_cast<Operation>(static_cast<int>(currentOp) + 1)(c);
}
template<class F, std::size_t...Is>
void magic_switch( std::size_t N, F&& f, std::index_sequence<Is...> ){
auto* pf = std::addressof(f);
using pF=decltype(pf);
using table_ptr = void(*)(pF);
static const table_ptr table[]={
[](pF){ std::forward<F>(*pf)( std::integral_constant<std::size_t, Is>{} ); }...
};
return table[N]( pf );
}
template<std::size_t Count, class F>
void magic_switch( std::size_t N, F&& f ){
return magic_switch( N, std::forward<F>(f), std::make_index_sequence<Count>{} );
}
This makes a jump table that invokes a lambda on a compile time constant, picking which entry based on a runtime constant. Which is very similar to how a switch case statement is compiled to sometimes.
void execute(Operation o) {
magic_switch<2>( std::size_t(o), [](auto I){
execute<Operation(I)>();
} );
}
Modifying it to return non-void is possible, but all branches must return the same type.