"A Proposal to Relax Constexpr Restrictions for some Reinterpret Casts" ?

241 views
Skip to first unread message

Peet

unread,
Nov 25, 2016, 6:32:31 AM11/25/16
to ISO C++ Standard - Future Proposals
Hello,

I was basically trying to implement a hash function in C++ using constant expressions (constexpr).
Sometimes it is necessary to cast a scalar type (or arrays) to cv unsigned/signed char* to simply get the bytes and do some calculation.
Although it seems that reinterpret_casts aren't allowed in constexpr (5.20/2.14).
Quickly googling this issue got me to this proposal: "A Proposal to Relax Constexpr Restrictions for some Reinterpret Casts" by Antony Polukhin [1].
This proposal relaxes the rule for reinterpret_cast in constexpr so that we can actually cast cv void* to cv unsigned/signed char*.
Although I couldn't find any discussions about this online, also it seems that the proposal hasn't been sent to the openstd mailing-list.
Does anyone know if this proposal is still "alive" and if this is being considered proposing?

Regards,
Nick

Mathias Gaunard

unread,
Nov 25, 2016, 10:32:50 AM11/25/16
to std-pr...@isocpp.org
I think you would have better luck with the new function bit_cast which might end up being constexpr.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/afbaf79e-305d-4408-98ab-5b35cfb11f27%40isocpp.org.

Peet Nick

unread,
Nov 28, 2016, 5:04:42 PM11/28/16
to std-pr...@isocpp.org
I am not sure how that would help? The destination type must have the same size as the source type, how would that help me getting the "raw byte view" of an scalar/pod?

Edward Catmur

unread,
Nov 28, 2016, 5:35:37 PM11/28/16
to ISO C++ Standard - Future Proposals
On Monday, 28 November 2016 22:04:42 UTC, Peet Nick wrote:
> I am not sure how that would help? The destination type must have the same size as the source type, how would that help me getting the "raw byte view" of an scalar/pod?

You would bit_cast to an array (or std::array) of unsigned char of the same size as your pod.

> On Fri, Nov 25, 2016 at 4:32 PM, Mathias Gaunard <mat...@gaunard.com> wrote:
>
> I think you would have better luck with the new function bit_cast which might end up being constexpr.
>
>
>
>
> On 25 November 2016 at 11:32, Peet <peet...@gmail.com> wrote:
>
> Hello,
>
>
> I was basically trying to implement a hash function in C++ using constant expressions (constexpr).
> Sometimes it is necessary to cast a scalar type (or arrays) to cv unsigned/signed char* to simply get the bytes and do some calculation.
> Although it seems that reinterpret_casts aren't allowed in constexpr (5.20/2.14).
> Quickly googling this issue got me to this proposal: "A Proposal to Relax Constexpr Restrictions for some Reinterpret Casts" by Antony Polukhin [1].
> This proposal relaxes the rule for reinterpret_cast in constexpr so that we can actually cast cv void* to cv unsigned/signed char*.
> Although I couldn't find any discussions about this online, also it seems that the proposal hasn't been sent to the openstd mailing-list.
> Does anyone know if this proposal is still "alive" and if this is being considered proposing?
>
>
> Regards,
> Nick
>
>
> [1] https://apolukhin.github.io/constexpr_algorithms/reinterpret.html
>
>
>
>
> --
>
> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
>
> To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
>
> To post to this group, send email to std-pr...@isocpp.org.
>
> To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/afbaf79e-305d-4408-98ab-5b35cfb11f27%40isocpp.org.
>
>
>
>
>
>
>
> --
>
> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
>
> To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

Peet Nick

unread,
Nov 28, 2016, 5:50:35 PM11/28/16
to std-pr...@isocpp.org
Ah, I understand. Although I understand this now, I am not entirely sure how it will be actually implemented. How would someone implement bit_cast as a constexpr without having std::memcpy constexpr?

To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Edward Catmur

unread,
Nov 28, 2016, 6:00:57 PM11/28/16
to std-pr...@isocpp.org

On 28 Nov 2016 22:50, "Peet Nick" <peet...@gmail.com> wrote:
>
> Ah, I understand. Although I understand this now, I am not entirely sure how it will be actually implemented. How would someone implement bit_cast as a constexpr without having std::memcpy constexpr?

They'd have to use a compiler intrinsic; according to [1] llvm already has a suitable opcode, so the other compilers would have to do the same, if they don't have an appropriate intrinsic available already.

Remember, it's fine for library functions to need compiler magic to implement; part of the job of the standard library is to provide standardized interfaces to such magic.

1. http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0476r0.html

>> To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/14dc989b-7a2f-478b-b16e-b9297fb1782f%40isocpp.org.
>
>
> --
> You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/6tkocdbwVGU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.


> To post to this group, send email to std-pr...@isocpp.org.

> To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJwqTS_OGEOUiUE6rSRrREV6Yx9%2B4Sj5gA8CDHeYgXnPwErW6Q%40mail.gmail.com.

Richard Smith

unread,
Nov 28, 2016, 7:01:39 PM11/28/16
to std-pr...@isocpp.org
On 28 November 2016 at 15:00, 'Edward Catmur' via ISO C++ Standard - Future Proposals <std-pr...@isocpp.org> wrote:

On 28 Nov 2016 22:50, "Peet Nick" <peet...@gmail.com> wrote:
>
> Ah, I understand. Although I understand this now, I am not entirely sure how it will be actually implemented. How would someone implement bit_cast as a constexpr without having std::memcpy constexpr?

They'd have to use a compiler intrinsic; according to [1] llvm already has a suitable opcode,

That doesn't help at all. Constant expression evaluation happens at a completely different layer from LLVM.

memcpy is fundamentally not possible to support in general within constant expression evaluation; consider:

  int n;
  constexpr int *p = &n; // ok
  constexpr intptr_t q = bit_cast<intptr_t>(p); // ok?
  static_assert(q > 0x1234567); // ok?!

Clearly this example must be ill-formed. But either that means you can't do the bit_cast in a constant expression or that you can evaluate an integer as part of a constant expression that you then can't do basic integer operations on.

However, we *can* support bit_cast for some pairs of source and destination types (we can't support types containing a pointer, reference, pointer-to-member, or class object with virtual functions or virtual bases because we don't know the bit pattern, we can't support source objects that have padding bits in locations where the destination needs a value, and we can't support unions within the destination because we wouldn't know the active member).

My hope is that bit_cast will provide access to a supportable subset of operations here at compile time and defer the rest to runtime.
>> To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

>>
>> To post to this group, send email to std-pr...@isocpp.org.
>> To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/14dc989b-7a2f-478b-b16e-b9297fb1782f%40isocpp.org.
>
>
> --
> You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/6tkocdbwVGU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Nicol Bolas

unread,
Nov 28, 2016, 9:07:57 PM11/28/16
to ISO C++ Standard - Future Proposals


On Monday, November 28, 2016 at 7:01:39 PM UTC-5, Richard Smith wrote:
On 28 November 2016 at 15:00, 'Edward Catmur' via ISO C++ Standard - Future Proposals <std-pr...@isocpp.org> wrote:

On 28 Nov 2016 22:50, "Peet Nick" <peet...@gmail.com> wrote:
>
> Ah, I understand. Although I understand this now, I am not entirely sure how it will be actually implemented. How would someone implement bit_cast as a constexpr without having std::memcpy constexpr?

They'd have to use a compiler intrinsic; according to [1] llvm already has a suitable opcode,

That doesn't help at all. Constant expression evaluation happens at a completely different layer from LLVM.

memcpy is fundamentally not possible to support in general within constant expression evaluation; consider:

  int n;
  constexpr int *p = &n; // ok
  constexpr intptr_t q = bit_cast<intptr_t>(p); // ok?
  static_assert(q > 0x1234567); // ok?!

Clearly this example must be ill-formed. But either that means you can't do the bit_cast in a constant expression or that you can evaluate an integer as part of a constant expression that you then can't do basic integer operations on.

This is precisely why `bit_cast` is a good thing. Because it's a function which knows both the source and destination types, we would be able to say that it is `constexpr` when doing certain conversions and not `constexpr` when doing others. For example, any conversion of a pointer to anything other than a pointer would not be `constexpr`. This would include within various types, so you couldn't have a `struct{int *p};` that you `bit_cast` to a `struct{intptr_t q};`.

The OP asked specifically about converting integers to their bit-representation to do hashing and so forth. `bit_cast` could be `constexpr` for such operations.

So there's no problem.

Myriachan

unread,
Dec 2, 2016, 8:32:34 PM12/2/16
to ISO C++ Standard - Future Proposals
On Monday, November 28, 2016 at 6:07:57 PM UTC-8, Nicol Bolas wrote:
This is precisely why `bit_cast` is a good thing. Because it's a function which knows both the source and destination types, we would be able to say that it is `constexpr` when doing certain conversions and not `constexpr` when doing others. For example, any conversion of a pointer to anything other than a pointer would not be `constexpr`. This would include within various types, so you couldn't have a `struct{int *p};` that you `bit_cast` to a `struct{intptr_t q};`.

The OP asked specifically about converting integers to their bit-representation to do hashing and so forth. `bit_cast` could be `constexpr` for such operations.

So there's no problem.

As far as I can tell, constexpr bit_cast would be useful for implementing things that'd otherwise require direct compiler support, such as std::numeric_limits<float>::infinity().  Am I right in this assumption?

Melissa

Thiago Macieira

unread,
Dec 2, 2016, 9:39:29 PM12/2/16
to std-pr...@isocpp.org
On sexta-feira, 2 de dezembro de 2016 17:32:34 PST Myriachan wrote:
> As far as I can tell, constexpr bit_cast would be useful for implementing
> things that'd otherwise require direct compiler support, such as
> std::numeric_limits<float>::infinity(). Am I right in this assumption?

Probably, but not for infinity(). That can be implemented by doing max() *
max().

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center

Reply all
Reply to author
Forward
0 new messages