将模板生成的 class 分配给具有相同布局的 C 结构
Assigning a template-generated class to a C struct with the same layout
如果我没理解错的话,对象'A'是这样定义的:
typedef struct {
int n;
float *p;
} myStruct;
myStruct A;
是一个聚合,在内存中的布局与对象“B”完全相同,定义为:
template <typename T> class myTemplateClass
{
public:
int n;
T* p;
};
myTemplateClass<float> B;
那么,有没有更优雅的赋值方式
A = B;
不用写
A = *(reinterpret_cast< myStruct *>(&B));
每次?
我问的原因是我必须调用一个库函数,该函数公开一个带有“myStruct”形式参数的接口,从以 myTemplateClass 形式保存我的数据的代码更加自然。
根据类型参数,您可以使 myTemplateClass<T>
从正确的 myStruct
派生。您可以为此使用模板专业化:
template <typename T> class myTemplateClass;
// Specialization for float
template <> class myTemplateClass<float> : public myStruct {};
// Specialization for int
template <> class myTemplateClass<int> : public myOtherStruct {};
// And so on for other types...
这样,您可以将 myTemplateClass<float>
的实例分配给 myStruct
,将 myTemplateClass<int>
的实例分配给 myOtherStruct
。 (奖励:您不必依赖 "same memory layout" 猜测。)
如果您从 mystruct 派生,那么,您可以在其上使用 static_cast。
如上所述,模板专业化也可以。
我每天都会 static_cast 而不是 reinterpret_cast。
下面是工作代码。
typedef struct {
int n;
float *p;
} myStruct;
myStruct A;
template <typename T> class myTemplateClass:public myStruct
{
public:
int n;
T* p;
};
//myTemplateClass<float> B;
typedef myTemplateClass<float> temp;
temp B;
int main()
{
A = *(static_cast< myStruct *>(&B));
这需要一些样板文件。每个 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);
}
在 C++11 中你必须添加一个 decltype
子句来显式地给出 return 值。基本上 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 );
}
};
最后写赋值:
template<class Lhs, class Rhs>
void assign_by_members( Lhs& lhs, Rhs const& rhs ) {
members(lhs) = members(rhs);
}
我们完成了。
任何声明自由函数 members
且 return 可分配给其他 members
的东西的任何人都可以工作。 tie
对引用进行逐元素赋值,所以一切都很好。
请注意,只有从分配的那个需要members
的const&
重载,并且只有分配给[的那个[=] =58=] 需要 members
的 &
重载。因此,如果赋值总是从 template
class 到 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;
}
};
它还进行测试以确定转换为的类型是否支持 members
。您可以更进一步,测试 members
return 值是否可以从 members(*this)
的 return 值分配给 return 值,但这会增加更多样板文件。
如果我没理解错的话,对象'A'是这样定义的:
typedef struct {
int n;
float *p;
} myStruct;
myStruct A;
是一个聚合,在内存中的布局与对象“B”完全相同,定义为:
template <typename T> class myTemplateClass
{
public:
int n;
T* p;
};
myTemplateClass<float> B;
那么,有没有更优雅的赋值方式
A = B;
不用写
A = *(reinterpret_cast< myStruct *>(&B));
每次?
我问的原因是我必须调用一个库函数,该函数公开一个带有“myStruct”形式参数的接口,从以 myTemplateClass 形式保存我的数据的代码更加自然。
根据类型参数,您可以使 myTemplateClass<T>
从正确的 myStruct
派生。您可以为此使用模板专业化:
template <typename T> class myTemplateClass;
// Specialization for float
template <> class myTemplateClass<float> : public myStruct {};
// Specialization for int
template <> class myTemplateClass<int> : public myOtherStruct {};
// And so on for other types...
这样,您可以将 myTemplateClass<float>
的实例分配给 myStruct
,将 myTemplateClass<int>
的实例分配给 myOtherStruct
。 (奖励:您不必依赖 "same memory layout" 猜测。)
如果您从 mystruct 派生,那么,您可以在其上使用 static_cast。 如上所述,模板专业化也可以。 我每天都会 static_cast 而不是 reinterpret_cast。
下面是工作代码。
typedef struct {
int n;
float *p;
} myStruct;
myStruct A;
template <typename T> class myTemplateClass:public myStruct
{
public:
int n;
T* p;
};
//myTemplateClass<float> B;
typedef myTemplateClass<float> temp;
temp B;
int main()
{
A = *(static_cast< myStruct *>(&B));
这需要一些样板文件。每个 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);
}
在 C++11 中你必须添加一个 decltype
子句来显式地给出 return 值。基本上 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 );
}
};
最后写赋值:
template<class Lhs, class Rhs>
void assign_by_members( Lhs& lhs, Rhs const& rhs ) {
members(lhs) = members(rhs);
}
我们完成了。
任何声明自由函数 members
且 return 可分配给其他 members
的东西的任何人都可以工作。 tie
对引用进行逐元素赋值,所以一切都很好。
请注意,只有从分配的那个需要members
的const&
重载,并且只有分配给[的那个[=] =58=] 需要 members
的 &
重载。因此,如果赋值总是从 template
class 到 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;
}
};
它还进行测试以确定转换为的类型是否支持 members
。您可以更进一步,测试 members
return 值是否可以从 members(*this)
的 return 值分配给 return 值,但这会增加更多样板文件。