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;
>
> 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