c++ - 将指向结构的指针转换为具有较少数量字段的另一种结构类型

标签 c++ pointers reflection struct reinterpret-cast

基本问题

我处于一个棘手的情况,需要获取指向结构的指针 mainset并将其转换为指向结构体 subset 的指针,其字段是 mainset 字段的连续子集,从第一个开始。如果有明确的行为,这样的事情可能吗?我意识到这是一件非常可怕的事情,但我有充分且令人沮丧的理由这样做[在底部为耐心的读者解释]。

我尝试在 OS X 上使用 clang 编译器实现一个似乎可以工作的实现:

#include <iostream>

struct mainset {
    size_t size;
    uint32_t reflex_size;
};

struct subset {
    size_t size;
};

using namespace std;
int main(int argc, char *argv[]) {
    mainset test = {1, 1};
    subset* stest = reinterpret_cast<subset*>(&test);
    std::cout << stest->size << std::endl;
}

正如我所料,输出确实是 1。但是,我想知道:我只是幸运地使用了特定的编译器和简单的情况(实际上我的结构更复杂),还是这通常可以工作?

还有一个后续问题:由于其他烦人的原因,我担心我可能需要制作更大的结构

struct mainset {
    uint32_t reflex_size;
    size_t size;
};

相反,额外的字段位于前面。我的实现可以扩展到这种情况吗?我尝试替换 &test&test+sizeof(test.reflex_size)但这没有用; cout 的输出声明为 0。

解释为什么我必须这样做

我的项目使用 GSL 库进行线性代数。该库使用以下形式的结构

struct gsl_block {
   size_t size;
   double* data;
}

和类似的结构,如 gsl_vectorgsl_matrix 。因此,我使用这些结构作为我的 C++ 类的成员;没问题。然而,我的项目最近需要的一个功能是使用 Reflex 启用对我的类的反射。工具,ROOT 生态系统的一部分。要在 Reflex 中启用这样的结构的反射,我必须添加一个注释,例如

struct gsl_block {
   size_t size;
   double* data; //[size]
}

此注释告诉 Reflex 数组的长度由字段 size 提供。相同结构的。通常是这样,但是 Reflex 和 ROOT 有一个非常不幸的限制:长度字段必须是 32 位。得知此限制不会很快得到修复,并且自己没有时间/资源来修复它,我正在寻找解决方法。我的想法是以某种方式嵌入一个与 gsl_block 位兼容的结构体在更大的结构中:

struct extended_gsl_block {
   size_t size;
   double* data; //[reflex_size]
   uint32_t reflex_size;
}

以及gsl_vector的类似内容和gsl_matrix ;我可以保证reflex_sizesize总是相等(都不大于~50),并且 Reflex 将能够正确解析此 header (我希望;如果需要 reflex_size 作为字段放在数据之前,则需要更困难的东西)。由于 GSL 例程使用指向这些结构的指针,所以我的想法是这样的:给定一个指针 extended_gsl_block* ,以某种方式获取指向字段 size 的指针和datareinterpret_cast这变成了gsl_block* .

最佳答案

你很幸运。

您作为示例显示的类符合标准布局类型的要求。

您可以在这里阅读更多内容:

http://en.cppreference.com/w/cpp/language/data_members#Standard_layout

您可以在编译器中测试这个前提:

static_assert(std::is_standard_layout<gsl_block>::value, "not a standard layout");

关于c++ - 将指向结构的指针转换为具有较少数量字段的另一种结构类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43238780/

相关文章:

c++,omnicppcomplete 不显示字符串的方法

c++ - 将 STL 数据结构传递给 opencl 内核

c++ - 在 QT 项目中使用 Crypto++ 静态库

c++ - 哪个版本的 safe_delete 更好?

c++ - 删除没有指定大小的指针数组

c++ - 为什么 std::extent 应用于 auto& 会产生零?

c# - 我如何使用 Reflection + C# 获取所有引用

java - 从我的 Android 库访问应用程序 R 类

reflection - Kotlin 父类(super class) Kclass

pointers - Golang 指针