I need to determine the offset of a certain indexed element of a tuple at compile time.
I tried this function, copied from https://stackoverflow.com/a/55071840/225186 (near the end),
template <std::size_t I, typename Tuple>
constexpr std::ptrdiff_t element_offset() {
Tuple p;
return
(char*)(&std::get<I>(*static_cast<Tuple *>(&p)))
- (char*)(static_cast<Tuple*>(&p))
;
}
including variants in which I eliminate p
and replace &p
by nullptr
.
This function seems to work well at runtime but I cannot evaluate it at compile time.
https://godbolt.org/z/MzGxfT1cc
int main() {
using Tuple = std::tuple<int, double, int, char, short, long double>;
constexpr std::size_t index = 3;
constexpr std::ptrdiff_t offset = element_offset<index, Tuple>(); // ERROR HERE, cannot evaluate constexpr context
Tuple t;
assert(( reinterpret_cast<char*>(&t) + offset == reinterpret_cast<char*>(&std::get<index>(t)) )); // OK, when compiles (without "constexpr" offset)
}
I understand this is probably because the reinterpret_cast
s cannot be done at compile time.
But so far it is basically the only function that proved to work (at runtime).
Is there a way to rewrite this function in a way that can be evaluated at compile type?
I also tried these approached list at the beginning of https://stackoverflow.com/a/55071840/225186, but they all give garbage results (at least in GCC) because they assume a certain ordering of the tuple elements and the offset are calculated by "walking" index by index and aligning bytes.