Reputation: 2553
Currently I am doing:
if constexpr(constexpr_bool_var1) {
auto arg1 = costly_arg1(); auto arg2 = costly_arg2();
if (costly_runtime_function(arg1, arg2)) {
// do X, possibly more constexpr conditions
// do Y
// ...
}
} else {
// do X, possibly more constexpr conditions
// do Y
// ...
}
One possible way is to convert the do X/Y etc. to one function doXY() and call it in both places, however it seems very unwieldy, as I have to write a function that solely exists for convenience of meta programming.
What I want is something like:
if not constexpr(constexpr_bool_var1 && some_magic(costly_runtime_function(arg1, arg2)) {
// do X, do Y
}
Another way is:
auto arg1 = costly_arg1(); // Unneeded extra work out not within constexpr
auto arg2 = costly_arg2();
if (constexpr_bool_var1 && costly_runtime_function(arg1, arg2)) {
} else {
// do X, possibly more constexpr conditions
// do Y
// ...
}
However here arg1 and arg2 are being declared outside the if condition so they will be needlessly instantiated.
Upvotes: 4
Views: 134
Reputation: 41760
You could use a lambda for that:
auto stuff = [&] {
// do X, possibly more constexpr conditions
// do Y
// ...
};
if constexpr(constexpr_bool_var1) {
auto arg1 = costly_arg1(); auto arg2 = costly_arg2();
if (costly_runtime_function(arg1, arg2)) {
stuff();
}
} else {
stuff();
}
And if your lambda can receive auto values, you could also pass variable of different types from inside the if
scope.
Upvotes: 0
Reputation: 7433
I’m not sure I understand your question correctly; your original code and your second alternative don’t express quite the same function (the meaning of costly_runtime_function
is reversed from “do X and Y” to “don’t do X and Y”), and in your first propoed alternative I don’t understand what your proposed syntax or what some_magic
is. I’m answering your question with the semantics of your original code sample.
The best way to handle this is probably with a flag for whether or not to do X and Y:
bool do_x_y = true;
if constexpr(constexpr_bool_var1) {
// Maybe we don't actually want X and Y
auto arg1 = costly_arg1(); auto arg2 = costly_arg2();
do_x_y = costly_runtime_function(arg1, arg2);
}
if (do_x_y) {
// do X, possibly more constexpr conditions
// do Y
// ...
}
Note that, as Andrei R. points out in the comments, the compiler can probably handle the optimization anyway. This makes it clearer to a human reader that you want this handled at compile time, though.
Upvotes: 3
Reputation: 69864
Here's one way. Whether it's more expressive/maintainable I cannot say.
#include <cstdlib>
#include <utility>
/*
* simulation
*/
void doX() {}
void doY() {}
int costly_arg1() { return 1; }
int costly_arg2() { return 2; }
bool costly_runtime_function(int, int) { return rand() < RAND_MAX / 2; }
constexpr bool constexpr_bool_var1 = true;
/*
* A functor that maybe does something
*/
template<class F>
struct maybe_do
{
constexpr maybe_do(F&& f) : f(std::move(f)) {}
constexpr void operator()() const
{
if (enabled)
f();
}
constexpr void enable(bool e) {
enabled = e;
}
F f;
bool enabled = true;
};
int main()
{
auto thing = maybe_do{
[] {
doX();
doY();
}
};
if constexpr(constexpr_bool_var1)
{
thing.enable(costly_runtime_function(costly_arg1(),
costly_arg2()));
}
thing();
}
Upvotes: 0