C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [[packed]] std::unaligned

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sat, 9 Dec 2023 01:44:25 +0000
On Fri, Dec 8, 2023 at 11:49 PM Thiago Macieira wrote:
>
> Something like it, but not that. The operations defined there must either be a
> very restricted set (get and set, probably) or be based on what the template
> type is. You can't do shifts on floating point and you can't do arithmetic on
> structures.


Yeah but there's no harm in defining those extra operators like
bit-shifting . . . you won't get a compiler error unless the
programmer actually tries to bit-shift an 'unaligned<double>'.

To be hyperpedantic about it though, you could do use 'requires
requires' as follows:

    template<typename U> requires requires { std::declval<T&>() +=
std::declval<U>(); }
    unaligned &operator+=(U &&u)
    {
            T tmp;
            std::memcpy(&tmp,buf,sizeof tmp);
            tmp &= std::forward<U>(u);
            std::memcpy(buf,&tmp,sizeof tmp);
            return *this;
    }

Or if you want to take into account whether the argument is an R-value
or an L-value, then even something like:

    template<typename U>
    unaligned &operator&=(U &&u)
    {
        if constexpr ( requires { std::declval<T&>() &= std::forward<U>(u); } )
        {
            T tmp;
            std::memcpy(&tmp,buf,sizeof tmp);
            tmp &= std::forward<U>(u);
            std::memcpy(buf,&tmp,sizeof tmp);
            return *this;
        }
        else static_assert(false, "You cannot use the &= operator with
these types");
    }

Actually I would save one level of indentation and rewrite that as follows:

    template<typename U>
    unaligned &operator&=(U &&u)
    {
        if constexpr ( !requires { std::declval<T&>() &=
std::forward<U>(u); } ) static_assert(false, "You cannot use the &=
operator with these types");
        T tmp;
        std::memcpy(&tmp,buf,sizeof tmp);
        tmp &= std::forward<U>(u);
        std::memcpy(buf,&tmp,sizeof tmp);
        return *this;
    }

To be honest though I'd go with my original code that doesn't apply
any constraints, and just let the compiler give the following error:

    <source>:25:13: error: invalid operands to binary expression
('double' and 'float')
       25 | tmp &= std::forward<U>(u);
          | ~~~ ^ ~~~~~~~~~~~~~~~~~~
    <source>:63:9: note: in instantiation of function template
specialization 'unaligned<double>::operator&=<float>' requested here
       63 | obj &= 4.2f;

Received on 2023-12-09 01:44:36