将模板生成的类分配给具有相同布局的C结构

如果我理解正确,那么对象’A’定义如下:

typedef struct { int n; float *p; } myStruct; myStruct A; 

是一个聚合,其内存布局与对象’B’完全相同,定义如下:

 template  class myTemplateClass { public: int n; T* p; }; myTemplateClass B; 

那么,是否有更优雅的分配方式

 A = B; 

而不是写

 A = *(reinterpret_cast(&B)); 

每次?

我的理由是我必须调用一个库函数,该函数使用“myStruct”forms的参数公开一个接口,从代码中以myTemplateClass的forms保存我的数据是非常自然的。

这需要一些样板。 每个myStruct两个函数,每个template两个函数。

myStruct的命名空间中注入以下两个函数:

 auto members( myStruct& s ) { return std::tie(sn, sp); } auto members( myStruct const& s ) { return std::tie(sn, sp); } 

在C ++ 11中,您必须添加一个decltype子句以显式提供返回值。 基本上按照声明的确切顺序tie成员。

myTemplateClass的主体中,声明一个执行类似操作的friend函数members

 template  class myTemplateClass { public: int n; T* p; friend auto members( myTemplateClass& self ) { return std::tie( self.n, self.p ); } friend auto members( myTemplateClass const& self ) { return std::tie( self.n, self.p ); } }; 

最后,写分配:

 template void assign_by_members( Lhs& lhs, Rhs const& rhs ) { members(lhs) = members(rhs); } 

我们完成了。

声明自由函数members任何人都返回可分配给其他members东西。 tie对引用进行了元素分配,所以一切都很好。

请注意,只有被分配的一个需要membersconst&重载,并且只有被分配的一个需要members&过载。 因此,如果赋值始终从template类转到C- struct ,则可以将该样板减半。

如果您不喜欢assign_by_members语法,则可以按如下方式覆盖operator O

 template  class myTemplateClass { public: // ... see above for code that goes here template())> operator O() const { O retval; assign_by_members( retval, *this ); return retval; } }; 

它还进行测试以确定转换为支持members的类型。 您可以更进一步测试members返回值是否可以从members(*this)的返回值members(*this)分配,但这会增加更多的样板。

您可以根据类型参数从正确的myStruct派生myTemplateClass 。 您可以使用模板专门化:

 template  class myTemplateClass; // Specialization for float template <> class myTemplateClass : public myStruct {}; // Specialization for int template <> class myTemplateClass : public myOtherStruct {}; // And so on for other types... 

这样,您可以将myTemplateClass实例分配给myStruct ,将myTemplateClass分配给myOtherStruct 。 (额外奖励:您不必依赖“相同的内存布局”猜测。)

如果你从mystruct派生,那么,你可以在它上面使用static_cast。 如上所述,模板专业化也会起作用。 我会在任何一天将static_cast放在reinterpret_cast上。

以下是工作代码。

 typedef struct { int n; float *p; } myStruct; myStruct A; template  class myTemplateClass:public myStruct { public: int n; T* p; }; //myTemplateClass B; typedef myTemplateClass temp; temp B; int main() { A = *(static_cast< myStruct *>(&B));