https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88895

--- Comment #6 from Martin Sebor <msebor at gcc dot gnu.org> ---
The C++ solution to this kind of problem is to use template specialization. 
It's a been a while since I wrote any real C++ code but this seems to work and
avoids the warnings

class PackRule
{
  template <class T, unsigned N>
  struct Packer;
public:
  const unsigned short offset_;
  const unsigned char width_;

  inline PackRule(const unsigned short offset, const unsigned char width) :
    offset_(offset), width_(width) {}

  template <typename T>
  inline void pack (void* to, const T v) const
  {
    unsigned char* tobyte = (unsigned char*)to + offset_;
    Packer<T, sizeof (T)>::pack (tobyte, v);
  }

  template<typename T>
  inline T unpack (const void* from, T* output) const
  {
    const unsigned char* frombyte = (const unsigned char*)from + offset_;
    return *output = Packer<T, sizeof (T)>::unpack (frombyte);
  }
};

template <class T, unsigned N>
struct PackRule::Packer
{
  static void pack (unsigned char *p, T x)
  {
    p[sizeof (T) - N] = (unsigned char)(x >> (N - 1) * __CHAR_BIT__);
    Packer<T, N - 1>::pack (p, x);
  }

  static T unpack (const unsigned char *p)
  {
    T x = (0xffU & (T)p[sizeof(T) - N]) << ((N - 1) * __CHAR_BIT__);
    return x | Packer<T, N - 1>::unpack (p);
  }
};

template <class T>
struct PackRule::Packer<T, 0>
{
  static void pack (unsigned char*, T) { }
  static T unpack (const unsigned char*) { return T (); }
};

int main ()
{
  PackRule p(0, 4);
  unsigned char buf[4];
  p.pack (buf, (unsigned int)444);
  unsigned int t;
  p.unpack (buf, &t);
}

Reply via email to