繁体   English   中英

将联盟强制转换为其成员类型之一

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM