Avoid function call on compile time false condition
c++, c++11, static-if, template-function
Solution
Yep.
template<bool b, typename Func, typename FuncElse>
struct compile_time_if_functor {
void operator()( Func&& f, FuncElse&& ) const{
std::forward<Func>(f)();
}
};
template<typename Func, typename FuncElse>
struct compile_time_if_functor<false, Func, FuncElse> {
void operator()( Func&&, FuncElse&& else_f ) const{
std:forward<FuncElse>(else_f)();
}
};
template<bool b, typename Func, typename Else>
void compile_time_if( Func&& f, Else&& elsef ) {
compile_time_if_functor<b, Func, Else> functor;
functor(
std::forward<Func>(f),
std::forward<Else>(elsef)
);
}
template<bool b, typename Func>
void compile_time_if( Func&& f ) {
auto do_nothing = []{};
compile_time_if<b>( std::forward<Func>(f), std::move(do_nothing) );
}
use:
int main() {
compile_time_if<expression>([&]{
// code that runs iff expression is true
});
compile_time_if<expression2>([&]{
// code that runs iff expression2 is true
},[&]{
// else clause, runs iff expression2 is false
});
}
note that the code inside the `{}` is compiled, but does not run, if it is in the wrong branch of the `if`. So that code needs to be well formed and legal at the type level, but it doesn't have to be legal to execute at run time. No creating arrays of size 0 in those lambdas!
A fancier method would let you chain if-else blocks indefinitely. I'd use named operator tricks if I wanted to do that.
First, change `compile_time_if` to return `std::integral_constant< bool, b >`.
Then, write `compile_time_else(Func&&)` and `compile_time_elseif<bool>(Func&&)` which return types that package that `Func` and override `operator*( std::true_type, X )` and `operator*( std::false_type, X )` to run or not run `Func` and return `std::true_type` or `std::false_type`.
The end goal would be this syntax:
If<expression>([&]{
// block 1
})*Else([&]{
// block 2
});
If<expression>([&]{
// block 1
})*ElseIf<expression2>([&]{
// block 2
})*ElseIf<expression3>([&]{
// block 3
})*Else([&]{
// block 4
});
allowing full-on cascading flow control. You could even go so far as to do:
compile_time_switch<value>(
Case<c0, FallThrough>(),
Case<c1>([&]{
// block 1
}),
Case<c2, Continue>([&]{
// block 2
}),
Case<c3>([&]{
// block 3
}),
Case<c4>([&]->CanContinue{
// block 4
if (condition) {
return Continue;
} else {
return Break;
}
}),
Case<c4>([&]{
}),
Default([&]{
})
};
but that is getting ahead of ourselves.
For ideas on how to mess around with duplicating C++ syntax in a way that allows the compiler to manipulate flow control at compile time, look at boost phoenix. I'm just including this here for completeness: actually writing that kind of stuff up is not all that practical, as some poor sod is going to have to maintain it, and the first few times you write this stuff up you are going to do a poor job!
Problem
I want to be able avoid calling a function when a condition is false when this is known at compile time. Now I use something like this: ``` template<bool Enabled> void fun(params) { //do nothing } template<> void fun<true>(params) { //do something with params. } ``` The thing I don't like with this aproach is that `params` are evaluated even if the function body is empty. I would like a solution when the function is not called at all and the params won't be evaluated when the condition is false(this might be optimized in the first case with empty function, but I can't assume this is true on every compiler). Is this even possible?