reinterpret_cast 的 CRTP 进入目标 class
CRTP with reinterpret_cast into target class
背景
我希望临时应用外观,而不是将它们烘焙到 class 本身。但是我需要对数据进行操作,所以我需要 this
可以从外观访问。这是一个小例子:
#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。前一段时间使用类似的东西,我很不幸能够逃脱它。
问题
如何使目标类型 class 的 this
在外观 class 中可用?
我对class布局的理解
在对象内部某处,以无序的方式,有数组和x_getter
。通过 reinterpret_cast
ing 它,我试图欺骗它认为 this
是 coordinates
,但是当它执行 operator[]
时,使用的偏移量有点偏离,它超出了对象,因此出现段错误。
这里的问题是 reinterpret_cast
不起作用,因为 this
指针不指向 coordinates
的开头 class 因为它继承自 array
在继承 x_getter
之前。此 class 的内存布局如下所示:
coordinates
|- std::array<double, 3>
|- x_getter
当你使用reinterpret_cast<T*>(this)
时,存储在this
指针中的地址是x_getter
对象的地址,但你强制编译器假定它实际上是[=14]的地址=] 对象。因此,取消引用这样一个指向派生 class 的指针会导致各种未定义的行为。
通常 CRTP 应该在方法内部使用 static_cast
:
double x() const
{
return (*static_cast<TDerived const *>(this))[0];
}
与 reinterpret_cast
不同,static_cast
会正确调整 this
指针以正确指向派生对象。
背景
我希望临时应用外观,而不是将它们烘焙到 class 本身。但是我需要对数据进行操作,所以我需要 this
可以从外观访问。这是一个小例子:
#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。前一段时间使用类似的东西,我很不幸能够逃脱它。
问题
如何使目标类型 class 的 this
在外观 class 中可用?
我对class布局的理解
在对象内部某处,以无序的方式,有数组和x_getter
。通过 reinterpret_cast
ing 它,我试图欺骗它认为 this
是 coordinates
,但是当它执行 operator[]
时,使用的偏移量有点偏离,它超出了对象,因此出现段错误。
这里的问题是 reinterpret_cast
不起作用,因为 this
指针不指向 coordinates
的开头 class 因为它继承自 array
在继承 x_getter
之前。此 class 的内存布局如下所示:
coordinates
|- std::array<double, 3>
|- x_getter
当你使用reinterpret_cast<T*>(this)
时,存储在this
指针中的地址是x_getter
对象的地址,但你强制编译器假定它实际上是[=14]的地址=] 对象。因此,取消引用这样一个指向派生 class 的指针会导致各种未定义的行为。
通常 CRTP 应该在方法内部使用 static_cast
:
double x() const
{
return (*static_cast<TDerived const *>(this))[0];
}
与 reinterpret_cast
不同,static_cast
会正确调整 this
指针以正确指向派生对象。