寻找对非POD类型相似,对offsetof的东西()

我正在寻找一种方式来获得一个C ++类,非POD性质的数据成员的偏移量。

这里的原因:

我想将数据存储在HDF5格式,它似乎是最适合我的那种材料(数值模拟输出),但它可能是一个相当C-型图书馆。 我想通过C ++接口来使用它,这需要我申报存储类型像这样(以下从这里和这里的文件(第4.3.2.1.1)):

class example { public: double member_a; int member_b; } //class example H5::CompType func_that_creates_example_CompType() { H5::CompType ct; ct.insertMember("a", HOFFSET(example, member_a), H5::PredType::NATIVE_DOUBLE); ct.insertMember("b", HOFFSET(example, member_b), H5::PredType::NATIVE_INT); return ct; } //func_that_creates_example_CompType

其中HOFFSET是使用对offsetof一个HDF-特定的宏。

的问题是,当然,这只要示例级变得它点点更多的其他功能,它不再是POD型,和因此使用对offsetof会给未定义的结果。

唯一的解决办法我能想到的是,首先导出我要存储到一个简单的结构数据,然后传递到高密度纤维板。 但这却涉及到数据拷贝,而这正是高密度纤维板是试图避免(为什么他们有这样的CompType使图书馆伸入你的对象以挽救他们的数据保存到文件)。

所以,我希望你有更好的想法。 理想情况下我会找一个便携式解决此问题,但如果达不到,你可以给我在x86和x86_64与海湾合作委员会的工作的想法我已经非常感谢。

-----后来追加-----

下面格雷格Hewgill建议将数据存储在一个简单的结构,然后从该继承建设实际的类。 对于高密度纤维板具体而言,我认为可能不会实际工作。 一个更复杂的使用场景比上面:

class base_pod { public: double member_a; int member_b; }; //class base_pod class derived_non_pod : private base_pod { public: //the following method is only virtual to illustrate the problem virtual double get_member_a() {return member_a; } }; //class derived_non_pod class that_uses_derived_non_pod { public: void whatever(); private: derived_non_pod member_c; }; //class that_uses_derived_non_pod

现在,当我们存储类that_uses_derived_non_pod的情况下,我们无法用语言形容它的内存布局,如果它有一个base_pod为member_c。 这将得到抵消错误的,因为derived_non_pod增加了时髦的东西(如虚函数表,我猜?)。

--------------解决方案-------------

格雷格Hewgill的解决方案可能是最好这个(可能与组成,而不是继承)。

但是,我认为,与海湾合作委员会在x86和x86_64,对offsetof将实际工作,即使对非POD类型的成员,只要它“有道理”。 因此,例如,它不会为成员的工作从虚基类继承的,因为在同一个额外的间接实施GCC。 但只要你坚持普通公众单继承,GCC只是恰巧铺陈的方式,这意味着每一个成员是一个从对象指针偏移访问你的对象,所以对offsetof实施,将给出正确的答案。

麻烦与这当然是,你必须忽视的警告,这意味着如果你做一些事情,不工作,你将取消引用贴近空指针。 从有利的一面,问题的原因可能是明显的在运行时。 在消极方面,eeew。

[编辑:我刚刚测试了这个在GCC 3.4.4,而实际上是警告升级到一个错误是由虚基类继承的成员时,得到的偏移量。 这是很好的。 我仍然会略有担心,海湾合作委员会(4,甚至,我不必手)的未来版本将更加严格,如果你采用这种方法的代码可能在未来停止编译]

根据你想如何便携式是,你可以使用对offsetof()即使在非POD类型。 这不是严格的一致性,但在对offsetof的方式()对GCC和MSVC实施后,它会与非POD类型工作​​在当前版本和最近的过去。

你可以在基类中声明的POD类型,然后扩展这个类(或许与private继承),以增加你的附加 ​​功能。

更新到您的更新:因为实例derived_non_pod也可视为一个base_pod因此偏移到数据成员必须相同。 关于实施,你的编译器的领域后,分配的虚函数表指针base_pod铺设了当derived_non_pod结构。

它发生,我认为,如果你使用私有继承编译器可能可以选择重新排序的数据字段。 这是不太可能这样做,然而,使遗产保护或市民会避免这种可能的陷阱。

我敢肯定,罗尔的同时考虑onebyone的答案回答涵盖了大部分你问什么。

struct A
{
int i;
};

class B: public A
{
public:
virtual void foo ()
{
}
};

int main ()
{
std::cout << offsetof (B, A::i) << std::endl;
}

随着G ++,上述输出4个,这是你所期望的,如果B的基类成员'我'前一个虚函数表。

它应该有可能虽然计算手动的偏移,即使在有虚拟的碱的情况下:

struct A1 {
int i;
};

struct A2 {
int j;
};

struct A3 : public virtual A2 {
};

class B: public A1, public A3 {
public:
virtual void foo () {
}
};

template <typename MostDerived, typename C, typename M>
ptrdiff_t calcOffset (MC::* member)
{
MostDerived d;
return reinterpret_cast<char*> (&(d.*member)) - reinterpret_cast<char*> (&d);
}

int main ()
{
B b;
std::cout << calcOffset<B> (&A2::j) << ", "
<< calcOffset<B> (&A1::i) << std::endl;
}

随着G ++,这个方案产出4和8。再次,这是与虚函数表为B的后面是虚拟基A2和它的成员'J'的第一个成员是一致的。 最后,非虚拟基A1和其成员的“i”。

关键的一点是,你总是基于最派生的对象,即在计算补偿。 B.如果成员都是私有,那么你可能需要添加一个“getMyOffset”呼吁每个成员。 此调用将执行计算其中,名称可以访问。

您可能会发现以下有用的了。 我认为这是很好的与你正在构建的HDF类型的对象相关联的所有的这样的:

struct H5MemberDef
{
const char * member_name;
ptrdiff_t offset;
H5PredType h5_type;
};

class B // ....
{
public:

// ...

static H5memberDef memberDef[];
};

H5MemberDef B::memberDef[] = {
{ "i", calcOffset<B> (&A1::i), H5::PredType::NATIVE_INT }
, { "j", calcOffset<B> (&A2::j), H5::PredType::NATIVE_INT }
, { 0, 0, H5::PredType::NATIVE_INT }
};

然后你就可以通过一个循环建立H5type:

H5::CompType func_that_creates_example_CompType(H5MemberDef * pDef) {
H5::CompType ct;
while (*pDef->member_name != 0)
{
ct.insertMember(pDef->member_name, pDef->offset, pDef->h5_type);
++pDef;
}
return ct;
}

现在,如果你添加一个成员到B或它的基地之一,那么一个简单的加法,以该表将导致生成正确的HDF类型。

这个问题一旦是因为你的结构/类不是外部的“C”,C ++编译器可以自由地重新排列和优化结构/类的布局,所以你可能最终取决于你的编译器的重新排列结构。

有预处理器(例如包的#pragma)标志对C样行为,但它们不是便携在大多数情况下。

请问使用指针成员的工作,而不是对offsetof()? 我知道,你可能需要做的铸造能够真正使用指针,因为我猜InsertMember作用于在运行时的最后一个参数指定类型的种种。

但与当前的解决方案,你周围的类型系统已经准备让我不知道你失去任何东西在那里。 除对会员的语法指针是可怕的。

这工作对我很好,我不明白为什么它不会:

#define myOffset(Class,Member) ({Class o; (size_t)&(o.Member) - (size_t)&o;})

分类:C# 时间:2015-03-14 人气:0
本文关键词: C#,HDF5,对offsetof
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 1.213 (s). 10 q(s)