我坚持使用一些生成的C代码,这有点乱。我目前正在将它包装到C ++ 11界面中,以免发生疯狂。
C代码包含已标记的联合。我希望能够提供一种简单的方法来阅读它们,例如:
template <typename U, typename T>
T readTaggedUnion(const U & un) {
return static_cast<T>(un);
}
这合法吗?
我也希望能够对此进行健全性检查,但看起来type_traits
在工会方面做得不多。并且联盟的所有标签都有自己生成的类型,因此无法以通用方式读取这些标签。
我已阅读continue,但它对我没有帮助。
编辑:我的代码是根据一些输入文件生成的,这些文件可以更改,我无法控制这些文件。我只知道输出结构如何,所以我知道哪些部分总是相同的,哪些部分取决于输入文件。
为名为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;
答案 0 :(得分:1)
我很想回复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;
}
}