I have a static_loop
construct like this
template <std::size_t n, typename F> void static_loop(F&& f) {
static_assert(n <= 8 && "static loop size should <= 8");
if constexpr (n >= 8)
f(std::integral_constant<size_t, n - 8>());
if constexpr (n >= 7)
f(std::integral_constant<size_t, n - 7>());
if constexpr (n >= 6)
f(std::integral_constant<size_t, n - 6>());
if constexpr (n >= 5)
f(std::integral_constant<size_t, n - 5>());
if constexpr (n >= 4)
f(std::integral_constant<size_t, n - 4>());
if constexpr (n >= 3)
f(std::integral_constant<size_t, n - 3>());
if constexpr (n >= 2)
f(std::integral_constant<size_t, n - 2>());
if constexpr (n >= 1)
f(std::integral_constant<size_t, n - 1>());
}
template <typename T> constexpr size_t tupleSize(T) { return tuple_size_v<T>; }
struct A {
int a;
int b;
void run() {
auto ab = std::make_tuple(std::ref(a), std::ref(b));
static_loop<tupleSize(ab)>([&](auto i) { std::get<i>(ab) = i; });
std::cout << a << " " << b << std::endl;
}
};
However, it fails to iterate over a tuple as listed above.
Suggestion: try with
I mean... you can't use
ab
(as value), in a constant expression, becauseab
isn't definedconstexpr
.And you can't define it
constexpr
because it's initialized usingstd::ref()
that isn'tconstexpr
.But you're not interested in
ab
as value to get the size of its type; you're interested only inab
type; so you can pass throughdecltype(ab)
.-- EDIT --
Off Topic suggestion.
Instead of
static_loop()
, you can use the classic way based onstd::index_sequence
(and template folding, available starting from C++17).I mean... if you define a
run_1()
function (withrun_1_helper()
helper) as followsyou can write
A
as followsOr, maybe better, simply using
std::apply()
, as followsChange
to:
That is, take the argument by reference to const, not by value. As-is, you're trying to copy a non-constexpr tuple in a constant expression - that can't work. By reference is fine since you're not actually reading the tuple.