If I have a tuple member variable where the types in the tuple are a parameter pack of a class template, I can apply a function to each object in the tuple with a static member function like this:
template<size_t I = 0, typename F, typename... Tp>
static void apply_to_foos(std::tuple<Tp...>& t, F func) {
auto& foo = std::get<I>(t);
func(foo);
if constexpr (I + 1 != sizeof...(Tp))
apply_to_foos<I + 1>(t, func);
}
so for example, if foos_is the tuple member variable, I could implement a member function over the foos via:
void frobnicate() {
apply_to_foos( foos_, [](auto& f){f.frob();} );
}
etc. however, if frobnicate had been const I run into the problem that foos_ will now be const, and apply_to_foos wants a non-const tuple. So for example this won't work (if foos are some kind of containers)
size_t size() const {
size_t sz = 0;
apply_to_foos( foos_, [&sz](auto& f){ sz += f.size();} );
return sz;
}
I could implement an overload of apply_to_foos that takes a const std::tuple<Tp...>&, const_cast to a non-const tuple and call the original overload, but, well, then I am just casting away const-ness.
The annoying thing about it is that the only part of apply_to_foos that cares about const-ness is the signature. Everything else will work with const values as long the const-ness is respected e.g. the lambda will need to take a reference to const value, etc. If I could cast from a const tuple to a tuple of consts then I could implement the const overload like this:
template<size_t I = 0, typename F, typename... Tp>
static void apply_to_foos(const std::tuple<Tp...>& t, F func) {
auto& tup_of_consts = const_tuple_to_tuple_of_consts(t);
apply_to_foos(tup_of_consts, func);
}
and the size() member function would just work naturally ... I feel like there must be an easier way to handle this though?