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

--- Comment #7 from Scott <scott.a.mayo at gmail dot com> ---
While that's brilliant,

1) I don't lack for ways to code around the problem, but whether or not 
I do, g++ nonetheless has a problem here.
2) At a guess, the recursive solution is avoiding the warnings because 
the compiler is unable to figure out if the shifts are a problem, which 
probably means it can't optimize your solution. I could probably have 
hidden the size of the shifts with less code than your specializations uses:

     volatile unsigned int q = 56; //now the compiler can't assume the 
shift is a problem
     (T)v << q;

or
     (T)v * (((uintmax_t)1 << 56))

but there goes hope of optimization, too. And for what I'm doing 
optimization is essential.

I'm not looking for ways to code work around a warning. I'm just asking 
for a bugfix in the compiler.

On 1/17/19 7:38 PM, msebor at gcc dot gnu.org wrote:
> 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