Date: Sat, 30 Nov 2024 16:14:46 -0500
> I don't mean you get sane programs out of doing UB, I'm saying the compiler is smart enough to allow it in runtime, but not in compile time.
I think we need to clarify the meaning of the term UB: it is a contract imposed on the program you write along with the runtime data your program intends to permit. The burden of ensuring no UB occur at runtime is the programmer's responsibility. In particular, a smart compiler will not try to give sane semantics out of UB: what the compiler does is interpreting the semantics the operation assuming the operation's input(s) will have, at runtime, a value for which the operation's behavior is exempt of UB.
There is no such thing as a smart compiler trying hard to get sane results out of UB. To the contrary, a smart enough compiler will try hard to fail compilation or diagnose if, given enough compile time information, it can prove that some operation will inevitably lead to UB at runtime. Moreover, if such an operation occurs in the body of an "if" statement, a smart enough compiler could optimize code and assume that the condition is always false and completely remove the "if" statement because a valid program can never mean to express such an operation. (For instance, if "x" an "y" are integer variables with values computed at runtime, the operation "x/(y-y)" is a guaranteed UB).
On November 30, 2024 1:47:51 p.m. EST, James via Std-Proposals <std-proposals_at_[hidden]> wrote:
>I don't mean you get sane programs out of doing UB, I'm saying the compiler
>is smart enough to allow it in runtime, but not in compile time.
>For example signed integer overflow is UB, you can't do it in compile time.
>But that doesn't mean you can't add two signed integers in compile time.
>It's only not allowed when it triggers a UB. Similarly, what I want to see
>is the same thing for type punning. Do whatever you want until you trigger
>UB.
>
>I'm telling you the examples that I'm currently making use of. I don't
>really wanna type out the exact code since it's way too long, but I'm sure
>you can see how this is usable with inplace_vector or similar types. I'm
>guessing you wanna see more about my second use case, so I'll show a
>little: https://godbolt.org/z/M75oobbqz
>Consider "IDelegateEntry" has more derived classes for different types of
>callables and I wanna have some callable type with type erasure so I can
>either store member functions, free functions, lambdas, etc. I wouldn't
>want to heap allocate the memory required for each callable, instead I'd
>wanna use something that has fixed size and makes use of placement new. But
>I can't use that in compile time at all due to placement new and
>reinterpret_cast not being allowed in compile time context.
>
>On Sat, Nov 30, 2024 at 9:18 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>>
>>
>> On Sat, 30 Nov 2024, 17:57 James, <james.business.84_at_[hidden]> wrote:
>>
>>> Well, my use cases involve having a blob of memory store some types on
>>> demand. One part is already mentioned via a paper linked in this
>>> discussion: uninitialized memory at compile time for stuff like
>>> inplace_vector. The other use case is polymorphism with making use of a
>>> fixed amount of memory. Specifically I use it for an alternative
>>> implementation of the std::function which is something else that cannot be
>>> used at compile time.
>>> The paper linked covers the first use case, but not the second one.
>>> Note: I want flexibility of how you wanna guarantee memory used
>>> appropriately, so I don't want the new standard type to have checks for
>>> that. There is a lot of examples of "in compile time, compiler won't allow
>>> UB, but in runtime you can do whatever you want"
>>>
>>
>>
>> No, there really aren't. UB is always wrong, runtime or not. Maybe what
>> you mean is that you can get away with writing bugs sometimes, and in
>> constant expressions the compiler won't let you.
>>
>> Maybe you're misusing the term "UB" and what you're trying to do is not
>> actually undefined, and so could potentially be allowed at compiler time,
>> but we can't tell because you still haven't given concrete examples.
>>
>> But if you're playing silly games with undefined behaviour, that's not
>> ever going to work at compile time. And might stop working at runtime too.
>>
>>
>>
>>> On Sat, Nov 30, 2024 at 8:40 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>>>
>>>>
>>>>
>>>> On Sat, 30 Nov 2024 at 17:30, James via Std-Proposals <
>>>> std-proposals_at_[hidden]> wrote:
>>>>
>>>>> Well, I can't say anything about being implementation defined or not.
>>>>> What I can say is it's currently impossible, so for this to work either
>>>>> standard needs to expand or make it implementation defined.
>>>>> std::bit_cast creates copies which is not the same thing.
>>>>> My main issue with the current state of the language is, you can do
>>>>> these things at runtime.
>>>>>
>>>>
>>>> What things? You haven't actually given an example of what you're doing
>>>> at runtime and want to do at compile-time. Most type punning is not
>>>> actually valid C++, although it depends exactly what you mean by type
>>>> punning.
>>>>
>>>>
>>>>
>>>>> I have various constructs that make use of type punning, but I can't
>>>>> use any of them at compile time. I need to have an alternative that solves
>>>>> the same problem to be able to do it in compile time. Even then behaviour
>>>>> isn't exactly the same.
>>>>>
>>>>> Regarding UB, compilers have all the information about literally
>>>>> anything when it's executed at compile time. Compilers are smart, they can
>>>>> handle it.
>>>>>
>>>>> On Sat, Nov 30, 2024 at 1:45 PM Sebastian Wittmeier via Std-Proposals <
>>>>> std-proposals_at_[hidden]> wrote:
>>>>>
>>>>>> The current typeless memory is either
>>>>>>
>>>>>> - std::byte, char, unsigned char
>>>>>>
>>>>>>
>>>>>>
>>>>>> As compile-time evaluation tries to avoid UB nearly completely and
>>>>>> also tries to not use any implementation-defined features, there is less
>>>>>> room for low-level inspection or modification.
>>>>>>
>>>>>>
>>>>>>
>>>>>> There is also constexpr std::bit_cast
>>>>>>
>>>>>>
>>>>>>
>>>>>> What usage examples do you have for the typeless_memory, which are not
>>>>>> implementation-defined, allow the compiler to check and avoid UB (which
>>>>>> e.g. entails an understanding of object lifetimes, types and memory
>>>>>> locations) and which cannot be solved with the current tools in the
>>>>>> standard library?
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> -----Ursprüngliche Nachricht-----
>>>>>> *Von:* James via Std-Proposals <std-proposals_at_[hidden]>
>>>>>> *Gesendet:* Sa 30.11.2024 10:56
>>>>>> *Betreff:* [std-proposals] std::typeless_memory (type punning)
>>>>>> *An:* std-proposals_at_[hidden];
>>>>>> *CC:* James <james.business.84_at_[hidden]>;
>>>>>> Currently you can do whatever you want at runtime when it comes to
>>>>>> type punning. Sure, all of them might not be safe, but you have some ways
>>>>>> to do it safely. However in compile time (as far as I know) there is no way
>>>>>> to achieve type punning.
>>>>>>
>>>>>> So I'd like to see this type, in standard library
>>>>>> https://godbolt.org/z/1dEjYW1hW
>>>>>>
>>>>>> It's only purpose is to allow treating some underlying memory as
>>>>>> whatever type you want in compile time without using extra memory. It would
>>>>>> also provide a shortcut for runtime usage
>>>>>> Currently you can't achieve that due to placement new and
>>>>>> reinterpret_cast not being usable in compile time context
>>>>>>
>>>>>> --
>>>>>> Std-Proposals mailing list
>>>>>> Std-Proposals_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>>
>>>>>> --
>>>>>> Std-Proposals mailing list
>>>>>> Std-Proposals_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>>
>>>>> --
>>>>> Std-Proposals mailing list
>>>>> Std-Proposals_at_[hidden]
>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>
>>>>
I think we need to clarify the meaning of the term UB: it is a contract imposed on the program you write along with the runtime data your program intends to permit. The burden of ensuring no UB occur at runtime is the programmer's responsibility. In particular, a smart compiler will not try to give sane semantics out of UB: what the compiler does is interpreting the semantics the operation assuming the operation's input(s) will have, at runtime, a value for which the operation's behavior is exempt of UB.
There is no such thing as a smart compiler trying hard to get sane results out of UB. To the contrary, a smart enough compiler will try hard to fail compilation or diagnose if, given enough compile time information, it can prove that some operation will inevitably lead to UB at runtime. Moreover, if such an operation occurs in the body of an "if" statement, a smart enough compiler could optimize code and assume that the condition is always false and completely remove the "if" statement because a valid program can never mean to express such an operation. (For instance, if "x" an "y" are integer variables with values computed at runtime, the operation "x/(y-y)" is a guaranteed UB).
On November 30, 2024 1:47:51 p.m. EST, James via Std-Proposals <std-proposals_at_[hidden]> wrote:
>I don't mean you get sane programs out of doing UB, I'm saying the compiler
>is smart enough to allow it in runtime, but not in compile time.
>For example signed integer overflow is UB, you can't do it in compile time.
>But that doesn't mean you can't add two signed integers in compile time.
>It's only not allowed when it triggers a UB. Similarly, what I want to see
>is the same thing for type punning. Do whatever you want until you trigger
>UB.
>
>I'm telling you the examples that I'm currently making use of. I don't
>really wanna type out the exact code since it's way too long, but I'm sure
>you can see how this is usable with inplace_vector or similar types. I'm
>guessing you wanna see more about my second use case, so I'll show a
>little: https://godbolt.org/z/M75oobbqz
>Consider "IDelegateEntry" has more derived classes for different types of
>callables and I wanna have some callable type with type erasure so I can
>either store member functions, free functions, lambdas, etc. I wouldn't
>want to heap allocate the memory required for each callable, instead I'd
>wanna use something that has fixed size and makes use of placement new. But
>I can't use that in compile time at all due to placement new and
>reinterpret_cast not being allowed in compile time context.
>
>On Sat, Nov 30, 2024 at 9:18 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>>
>>
>> On Sat, 30 Nov 2024, 17:57 James, <james.business.84_at_[hidden]> wrote:
>>
>>> Well, my use cases involve having a blob of memory store some types on
>>> demand. One part is already mentioned via a paper linked in this
>>> discussion: uninitialized memory at compile time for stuff like
>>> inplace_vector. The other use case is polymorphism with making use of a
>>> fixed amount of memory. Specifically I use it for an alternative
>>> implementation of the std::function which is something else that cannot be
>>> used at compile time.
>>> The paper linked covers the first use case, but not the second one.
>>> Note: I want flexibility of how you wanna guarantee memory used
>>> appropriately, so I don't want the new standard type to have checks for
>>> that. There is a lot of examples of "in compile time, compiler won't allow
>>> UB, but in runtime you can do whatever you want"
>>>
>>
>>
>> No, there really aren't. UB is always wrong, runtime or not. Maybe what
>> you mean is that you can get away with writing bugs sometimes, and in
>> constant expressions the compiler won't let you.
>>
>> Maybe you're misusing the term "UB" and what you're trying to do is not
>> actually undefined, and so could potentially be allowed at compiler time,
>> but we can't tell because you still haven't given concrete examples.
>>
>> But if you're playing silly games with undefined behaviour, that's not
>> ever going to work at compile time. And might stop working at runtime too.
>>
>>
>>
>>> On Sat, Nov 30, 2024 at 8:40 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>>>
>>>>
>>>>
>>>> On Sat, 30 Nov 2024 at 17:30, James via Std-Proposals <
>>>> std-proposals_at_[hidden]> wrote:
>>>>
>>>>> Well, I can't say anything about being implementation defined or not.
>>>>> What I can say is it's currently impossible, so for this to work either
>>>>> standard needs to expand or make it implementation defined.
>>>>> std::bit_cast creates copies which is not the same thing.
>>>>> My main issue with the current state of the language is, you can do
>>>>> these things at runtime.
>>>>>
>>>>
>>>> What things? You haven't actually given an example of what you're doing
>>>> at runtime and want to do at compile-time. Most type punning is not
>>>> actually valid C++, although it depends exactly what you mean by type
>>>> punning.
>>>>
>>>>
>>>>
>>>>> I have various constructs that make use of type punning, but I can't
>>>>> use any of them at compile time. I need to have an alternative that solves
>>>>> the same problem to be able to do it in compile time. Even then behaviour
>>>>> isn't exactly the same.
>>>>>
>>>>> Regarding UB, compilers have all the information about literally
>>>>> anything when it's executed at compile time. Compilers are smart, they can
>>>>> handle it.
>>>>>
>>>>> On Sat, Nov 30, 2024 at 1:45 PM Sebastian Wittmeier via Std-Proposals <
>>>>> std-proposals_at_[hidden]> wrote:
>>>>>
>>>>>> The current typeless memory is either
>>>>>>
>>>>>> - std::byte, char, unsigned char
>>>>>>
>>>>>>
>>>>>>
>>>>>> As compile-time evaluation tries to avoid UB nearly completely and
>>>>>> also tries to not use any implementation-defined features, there is less
>>>>>> room for low-level inspection or modification.
>>>>>>
>>>>>>
>>>>>>
>>>>>> There is also constexpr std::bit_cast
>>>>>>
>>>>>>
>>>>>>
>>>>>> What usage examples do you have for the typeless_memory, which are not
>>>>>> implementation-defined, allow the compiler to check and avoid UB (which
>>>>>> e.g. entails an understanding of object lifetimes, types and memory
>>>>>> locations) and which cannot be solved with the current tools in the
>>>>>> standard library?
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> -----Ursprüngliche Nachricht-----
>>>>>> *Von:* James via Std-Proposals <std-proposals_at_[hidden]>
>>>>>> *Gesendet:* Sa 30.11.2024 10:56
>>>>>> *Betreff:* [std-proposals] std::typeless_memory (type punning)
>>>>>> *An:* std-proposals_at_[hidden];
>>>>>> *CC:* James <james.business.84_at_[hidden]>;
>>>>>> Currently you can do whatever you want at runtime when it comes to
>>>>>> type punning. Sure, all of them might not be safe, but you have some ways
>>>>>> to do it safely. However in compile time (as far as I know) there is no way
>>>>>> to achieve type punning.
>>>>>>
>>>>>> So I'd like to see this type, in standard library
>>>>>> https://godbolt.org/z/1dEjYW1hW
>>>>>>
>>>>>> It's only purpose is to allow treating some underlying memory as
>>>>>> whatever type you want in compile time without using extra memory. It would
>>>>>> also provide a shortcut for runtime usage
>>>>>> Currently you can't achieve that due to placement new and
>>>>>> reinterpret_cast not being usable in compile time context
>>>>>>
>>>>>> --
>>>>>> Std-Proposals mailing list
>>>>>> Std-Proposals_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>>
>>>>>> --
>>>>>> Std-Proposals mailing list
>>>>>> Std-Proposals_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>>
>>>>> --
>>>>> Std-Proposals mailing list
>>>>> Std-Proposals_at_[hidden]
>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>
>>>>
Received on 2024-11-30 21:14:55