[英]Casting a union to one of its member types
我陷入了一些生成的C代码,这有点混乱。 我目前正在将其包装到C ++ 11接口中,以免发疯。
C代码包含标记的联合。 我希望能够提供一种简单的方法来读取它们,例如:
template <typename U, typename T>
T readTaggedUnion(const U & un) {
return static_cast<T>(un);
}
这合法吗?
我也很乐意对此进行完整性检查,但是看起来type_traits
在联合方面没有提供太多帮助。 联合的所有标记都有其自己的生成类型,因此无法以通用方式读取它们。
我已经读过c ++将联合强制转换为其成员类型之一,但这对我没有帮助。
编辑:我拥有的代码是根据一些输入文件生成的,这些文件可以更改,而我无法控制这些文件。 我只知道输出的结构,因此我知道哪些部分将始终相同,哪些取决于输入文件。
为名为TestChoice的结构生成的代码的示例,其中可以包含4种不同的内容:
/* Dependencies */
typedef enum TestChoice_PR {
TestChoice_PR_NOTHING, /* No components present */
TestChoice_PR_integer,
TestChoice_PR_optional,
TestChoice_PR_enm,
TestChoice_PR_setof
} TestChoice_PR;
/* TestChoice */
typedef struct TestChoice {
TestChoice_PR present;
union TestChoice_u {
INTEGER_t integer;
TestOptional_t optional;
TestEnumType_t enm;
TestSetOf_t setof;
} choice;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx; // This is not relevant
} TestChoice_t;
我很想返回boost::variant<Ts...>
(或者如果可以升级到C ++ 17,则为std::variant
)。
任何状况之下
// quick test to ensure we aren't casting from a non-union:
template<class U>
void union_test( U const volatile& ) {
static_assert( std::is_union< U >::value, "only unions allowed as an argument" );
}
template<class T, class U>
T union_cast( U const& u ) {
union_test(u);
using pT = typename std::remove_reference<T>::type;
return std::forward<T>(*(pT const*)std::addressof(u));
}
template<class T, class U>
T union_cast( U const&& u ) {
union_test(u);
using pT = typename std::remove_reference<T>::type;
return std::forward<T>(*(pT const*)std::addressof(u));
}
template<class T, class U>
T union_cast( U&& u ) {
union_test(u);
using pT = typename std::remove_reference<T>::type;
return std::forward<T>(*(pT*)std::addressof(u));
}
采用:
struct pt {
int x,y;
};
union x {
int a;
double d;
pt p;
};
void foo( int type, x in ) {
switch(type) {
case 0:
std::cout << union_cast<int>(in) << "\n";
return;
case 1:
std::cout << union_cast<double>(in) << "\n";
return;
case 2:
std::cout << union_cast<pt>(in).x << "," << union_cast<pt>(in).y << "\n";
return;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.