I have wrote the following code to get the offset of a tuple element
template<size_t Idx,class T>
constexpr size_t tuple_element_offset() {
return static_cast<size_t>(
reinterpret_cast<char*>(&std::get<Idx>(*reinterpret_cast<T*>(0))) - reinterpret_cast<char*>(0));
}
This is actually similar to the implementation of the offsetof macro.
It looks ugly, but compiles and works fine on gcc-4.6
typedef std::tuple<int,char,long> mytuple;
mytuple var = std::make_tuple(4,'c',1000);
char * ptr = reinterpret_cast<char*>(&var);
long * pt = reinterpret_cast<long*>(ptr+tuple_element_offset<2,mytuple>());
std::cout << *pt << std::endl;
prints “1000”.
I don’t know too much about constexpr, so my questions are:
- Is it legal c++?
- More important, why I am allowed to call
std::get (which is non constexpr)
inside a constexpr function?
As far as I understand constexpr, the compiler is forced to evaluate the result
of the expression at compile time, so no zero-dereferentiation can occurs in practice.
If by “legal” you mean “well-formed,” then, yes.
If by “legal” you mean “valid and will work on any compiler and Standard Library implementation, then, no, because
std::tupleis not POD.Basically, a
constexprfunction doesn’t necessarily have to consist of just a constant expression. If you tried to use yourtuple_element_offset()function in a constant expression, you’d get a compilation error.The idea is that a function might be usable in a constant expression in some circumstances but not in others, so there isn’t a restriction that a
constexprfunction must always be usable in a constant expression (since there isn’t such a restriction, it’s also possible that a particularconstexprfunction might never be usable in a constant expression, as is the case with your function).The C++0x draft has a good example (from 5.19/2):