Reputation: 2208
I'd like facades to be applied on ad-hoc basis, and not baking them into the class itself. But I need to operate on the data, so I need this
to be accessible from the facade. Here is a small example:
#include <array>
#include <iostream>
template <typename T>
struct x_getter
{
friend T;
double x() const
{
return (*real_self)[0];
}
void x(double new_x)
{
(*real_self)[0] = new_x;
}
private:
T* real_self = reinterpret_cast<T*>(this);
x_getter() = default; //prevents accidental creation
};
struct coordinates : std::array<double, 3>, x_getter<coordinates>
{
using std::array<double, 3>::array;
};
int main()
{
coordinates origin{};
std::cout << origin.x();
origin.x(12.7);
std::cout << ' ' << origin.x() << '\n';
}
It segfaults. Using something similar a while back, I got unlucky to be able to get away with it.
How do I make this
with type of target class be available in facade class?
Somewhere inside of the object, in unordered manner, there are array and x_getter
. By reinterpret_cast
ing it, I'm trying to trick it to think that this
is coordinates
, but when it performs operator[]
, the offset which is used is a bit off, which goes outside of the object, thus segfaulting.
Upvotes: 3
Views: 275
Reputation: 37600
The problem here is that reinterpret_cast
does not work because this
pointer does not point at the beginning of coordinates
class since it inherits from array
before inheriting from x_getter
. The memory layout for this class looks like this:
coordinates
|- std::array<double, 3>
|- x_getter
When you use reinterpret_cast<T*>(this)
the address stored in this
pointer is the address of x_getter
object, but you force compiler to assume that it is actually an address of coordinates
object. So dereferencing such a pointer to derived class leads to all kinds of undefined behavior.
Typically CRTP should use static_cast
inside of method:
double x() const
{
return (*static_cast<TDerived const *>(this))[0];
}
Unlike reinterpret_cast
, static_cast
will properly adjust this
pointer to correctly point at derived object.
Upvotes: 3