C++ 带模板的类型双关

C++ 带模板的类型双关,c++,c++11,templates,type-punning,C++,C++11,Templates,Type Punning,为了通过模板实现这些方法,我必须检查某人的笨拙代码,这些代码使用了20多个联合,并根据从字节数组双关并将数据复制到字节数组的方法的数量(第二个是字符) 模板类类型\u punner { T&p; 无符号字符*pun; 公众: 类型双关语(T&ref):p(ref),双关语(重新解释铸型(&p)) { static_assert(std::is_pod::value,“type_punner只能用于pod”); } 内联无符号字符和at(标准::大小\u t i) { #ifdef QT_调试 如

为了通过模板实现这些方法,我必须检查某人的笨拙代码,这些代码使用了20多个联合,并根据从字节数组双关并将数据复制到字节数组的方法的数量(第二个是字符)

模板类类型\u punner
{
T&p;
无符号字符*pun;
公众:
类型双关语(T&ref):p(ref),双关语(重新解释铸型(&p))
{
static_assert(std::is_pod::value,“type_punner只能用于pod”);
}
内联无符号字符和at(标准::大小\u t i)
{
#ifdef QT_调试
如果(!(i
只有当我保持标准兼容并通过返回的引用分配新值时,我担心的才是有效的

只有当我保持标准兼容并通过返回的引用分配新值时,我担心的才是有效的


它是有效的,因为这些引用是特殊的窄字符类型。

您的代码似乎是合法的。有一些改进:

constexpr bool k_little_endian
#if (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
  = true;
#else
  = false;
#endif
constexpr bool k_debug
#ifdef QT_DEBUG
  = true;
#else
  = false;
#endif

template <class T,
  bool little_endian = k_little_endian,
  bool debug = k_debug
>
class type_punner {
  T* p;
  unsigned char* pun() const { return reintepret_cast<unsigned char*>(p); }
public:
  static_assert(std::is_pod<T>::value, "type_punner can be used only for POD");
  type_punner(T& ref):
    p (std::addressof(ref))
  {}
  type_punner(type_punner const&)=default;
  type_punner()=delete;

  unsigned char& at(std::size_t i) const noexcept(!debug) {
    if (debug && !(i<size())) throw std::out_of_range( __FUNCTION__ );
    if (little_endian)
      return pun()[i];
    else
      return pun()[size() - i - 1];
  }

  unsigned char& reverse_at(std::size_t i) const noexcept(!debug) {
    if(debug && !(i < size())) throw std::out_of_range(__FUNCTION__);
    if (little_endian)
      return pun()[size() - i - 1];
    else
      return pun()[i];
  }
  // = 0 is  LSB
  unsigned char& operator[](std::size_t i) const noexcept(!debug) {
    return at(i);
  }
  static constexpr std::size_t size() noexcept(true) { return sizeof(T); }
};
constexpr bool k_little_endian
#if(Q_字节顺序==Q_小端)
=正确;
#否则
=假;
#恩迪夫
constexpr bool k_调试
#ifdef QT_调试
=正确;
#否则
=假;
#恩迪夫
模板
类类型\u punner{
T*p;
无符号char*pun()常量{return reintepret_cast(p);}
公众:
static_assert(std::is_pod::value,“type_punner只能用于pod”);
类型(T&ref):
p(标准::地址(参考))
{}
类型\u punner(类型\u punner const&)=默认值;
键入\ u punner()=删除;
unsigned char&at(std::size\u t i)const noexcept(!debug){

如果(调试&&!(依标准,无论如何,这都是未定义的行为。你的工作是确保你不产生hydras。@DeiDei我不产生hydras实际上,这不是同事创建hydras的最糟糕的例子。关于转换到角色类型指针等的规则发生了什么?真的,像这样的不确定的评论没有帮助,顺便说一句,这是没有办法的,因为A)目的是显示数据并按相反或直接顺序打包B)只有C++才是有用的,这是有趣的参考字段!关于移动宏的好主意,<代码> conxPRP< /COD>不支持,但是<代码> const 应该足够了。我使用宏定义插入它,以防升级,并且对于两个使用内联的编译器,它不是RununDad。(它从不在没有内联的情况下展开,或者它展开每个函数)并且不在类中存储引用,static_assert()只适用于函数体,不支持默认或删除的方法。我当然会用生成的pun()而不是noexcept(!debug)进行实验?我从来没有看到过这一点before@Swift它统计“如果
debug
为false,这保证不会抛出,但如果
debug
为true,则可能抛出。”啊..查找了它。也不支持,仅抛出()是,但很高兴知道。另外考虑一下,使用该模板参数,我不再需要reverse_at。at和reverse_at从未在同一上下文中使用,所以我可以用!k_little_endian声明punner。更多的九头蛇头掉落
constexpr bool k_little_endian
#if (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
  = true;
#else
  = false;
#endif
constexpr bool k_debug
#ifdef QT_DEBUG
  = true;
#else
  = false;
#endif

template <class T,
  bool little_endian = k_little_endian,
  bool debug = k_debug
>
class type_punner {
  T* p;
  unsigned char* pun() const { return reintepret_cast<unsigned char*>(p); }
public:
  static_assert(std::is_pod<T>::value, "type_punner can be used only for POD");
  type_punner(T& ref):
    p (std::addressof(ref))
  {}
  type_punner(type_punner const&)=default;
  type_punner()=delete;

  unsigned char& at(std::size_t i) const noexcept(!debug) {
    if (debug && !(i<size())) throw std::out_of_range( __FUNCTION__ );
    if (little_endian)
      return pun()[i];
    else
      return pun()[size() - i - 1];
  }

  unsigned char& reverse_at(std::size_t i) const noexcept(!debug) {
    if(debug && !(i < size())) throw std::out_of_range(__FUNCTION__);
    if (little_endian)
      return pun()[size() - i - 1];
    else
      return pun()[i];
  }
  // = 0 is  LSB
  unsigned char& operator[](std::size_t i) const noexcept(!debug) {
    return at(i);
  }
  static constexpr std::size_t size() noexcept(true) { return sizeof(T); }
};