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

Eos*_*ern 0 c c++ templates aggregation data-structures

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

typedef struct {
    int n;
    float *p;
} myStruct;
myStruct A;
Run Code Online (Sandbox Code Playgroud)

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

template <typename T> class myTemplateClass
{
public:
    int n;
    T*  p;
};
myTemplateClass<float> B;
Run Code Online (Sandbox Code Playgroud)

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

A = B;
Run Code Online (Sandbox Code Playgroud)

而不是写

A = *(reinterpret_cast< myStruct *>(&B));
Run Code Online (Sandbox Code Playgroud)

每次?

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

Yak*_*ont 5

这需要一些样板.每个myStruct功能两个,每个功能两个template.

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

auto members( myStruct& s ) {
  return std::tie(s.n, s.p);
}
auto members( myStruct const& s ) {
  return std::tie(s.n, s.p);
}
Run Code Online (Sandbox Code Playgroud)

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

在体内myTemplateClass,声明一个类似的friend函数members:

template <typename T>
class myTemplateClass {
public:
  int n;
  T*  p;
  friend auto members( myTemplateClass<T>& self ) {
    return std::tie( self.n, self.p );
  }
  friend auto members( myTemplateClass<T> const& self ) {
    return std::tie( self.n, self.p );
  }
};    
Run Code Online (Sandbox Code Playgroud)

最后,写分配:

template<class Lhs, class Rhs>
void assign_by_members( Lhs& lhs, Rhs const& rhs ) {
  members(lhs) = members(rhs);
}
Run Code Online (Sandbox Code Playgroud)

我们完成了.

任何宣称自由函数members返回可分配给其他members作品的人. tie在引用上进行元素分配,所以一切都很好.

只有一个被分配注意需求const&的超载members,只有一个被分配需要&的过载members.因此,如果赋值始终从template类到C- struct,则可以将该样板减半.

如果您不喜欢assign_by_members语法,可以覆盖operator O如下:

template <typename T>
class myTemplateClass {
public:
// ... see above for code that goes here
  template<class O,class=decltype(members(std::declval<O>())>
  operator O() const {
    O retval;
    assign_by_members( retval, *this );
    return retval;
  }
};
Run Code Online (Sandbox Code Playgroud)

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