Example
#include <cassert>
consteval int f(int i) { return i; }
constexpr int g(int i) {
if consteval {
return f(i) + 1; // ok: immediate function context
} else {
return 42;
}
}
consteval int h(int i) {
return f(i) + 1; // ok: immediate function context
}
static_assert(42 + 1 == h(42));
int main() {
int i = 42;
//h(i); // error: the value of 'i' is not usable in a constant expression
assert(42 == g(i));
}
Puzzle
- Can you implement a
add_or_sub
algorithm which addsargs…
toN
in consteval context and subsargs...
fromN
otherwise?
template<auto N = 0>
constexpr auto add_or_sub = [](const auto... args); // TODO
int main() {
using namespace boost::ut;
"add or sub test"_test = [] {
should("add in consteval context") = [] {
expect(constant<0_i == add_or_sub<0>()>);
expect(constant<1_i == add_or_sub<0>(1)>);
expect(constant<2_i == add_or_sub<1>(1)>);
expect(constant<4_i == add_or_sub<1>(1, 2)>);
expect(constant<16_i == add_or_sub<2>(3, 4, 7)>);
};
should("sub in non-consteval context") = [] {
expect(0_i == add_or_sub<0>());
expect(-1_i == add_or_sub<0>(1));
expect(0_i == add_or_sub<1>(1));
expect(-2_i == add_or_sub<1>(1, 2));
expect(-12_i == add_or_sub<2>(3, 4, 7));
const auto i = 42;
expect(-44_i == add_or_sub<>(2, i));
auto x = 7;
expect(-51_i == add_or_sub<1>(1, x, 2, i));
};
};
}
Solutions
template<auto N = 0>
constexpr auto add_or_sub = [](const auto... args) {
if consteval {
return (N + ... + args);
} else {
return (N - ... - args);
}
};
template<auto N = 0>
constexpr auto add_or_sub = [](const auto... args) {
const auto sum_of_args = (args + ... + 0);
if consteval {
return N + sum_of_args;
} else {
return N - sum_of_args;
}
};