C++ Logo

STD-PROPOSALS

Advanced search

Subject: Re: [std-proposals] std::as
From: Jordi Vilar (development_at_[hidden])
Date: 2020-11-05 14:34:55


Yes, I used the comparison to vector to show that both approaches are
already present in the standard, not as an example of consistency.

In this regards, what I propose is similar to new and and
new(std::nothrow). But the semantics in this case is different, as nothrow
is not introducing any ub in any case, just requires to check the resulting
pointer, so better to use another constant, as std::unchecked.

El dj., 5 de nov. 2020, 20:54, Ryan P. Nicholl <rnicholl_at_[hidden]> va
escriure:

> std::unchecked would work. But I don't like how you have both under "get"
> in comparison to e.g. vector where the overloads are separate. Feels
> inconsistent.
>
> More generally, std::as could be overloaded to work on unions too.
>
>
> --
> Ryan P. Nicholl
> Tel: (678)-358-7765
> Personal Email: rnicholl_at_[hidden]
> Work Email: ryan.nicholl_at_[hidden]
> Tox:
> 52B3A61CDAF88BCC854F568933F071E3530600CDBA3D5354AADC9AD179575D68021AE959719D
>
>
>
>
>
>
> -------- Original Message --------
> On Nov 5, 2020, 13:27, Jordi Vilar via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>
> I understand the problem you are trying to solve, it is a quite
> common pattern, being in an execution path in which we know the alternative
> held by the variant. For instance:
>
> if (has_alternative<alternative_type>(variant_object))
> {
> // it is now safe to get the alternative without checking.
> }
>
> but for this escenario, it is possible to do
>
> if (auto *alternative = std::get_if<alternative_type>(&variant_object))
> {
> // it is now safe to dereference the alternative pointer
> }
>
> I know, it is ugly and doesn't communicate properly the intent.
>
> This is the same case as avoiding the range check in std::vector::at()
> with std::vector::operator[]() subscript operator in:
>
> if (i < vector.size())
> {
> // it is now safe to do vector[i]
> }
>
> In this case, for historical reasons we have both methods. But in case of
> requiring this optimized path for variants, I would suggest to not adding a
> new function and pollute even more the std with different names for
> different patterns/idioms but overloading the current std::get with an
> overload discriminant object like std::nothrow:
>
> auto& variant = std::get<variant_type>(variant, std::nothrow);
>
> Or we could define a new std::nocheck constant to be reused in any other
> unchecked overload. In this way, the intent is clear.
>
> Invoking std::get with std::nothrow (or std::nocheck or whatever other
> symbol we could propose) would be undefined behavior when calling it when
> the variant holds a different alternative as subscript operator does when
> performing an out of bounds access to a std::vector. It is elegant, clear,
> safe and efficient.
>
> I hope this proposal helps,
>
> Jordi Vilar
>
> Missatge de Avi Kivity via Std-Proposals <std-proposals_at_[hidden]>
> del dia dj., 5 de nov. 2020 a les 18:10:
>
>> How can the reader of *get_if() tell if the author intended this
>> optimization, or was just lazy?
>>
>>
>> Function names should communicate intent. "get_if()" communicates that
>> you don't know if the variant holds the the type you are asking for or not.
>> *get_if() communicates that you forgot to check.
>>
>>
>> My preference would be static_variant_cast<>, following static_cast<> and
>> static_pointer_cast<>. The latter two communicate that the author knows
>> there is a safety violation if some other check is not performed, and
>> confirms they are aware of it, enough to have typed such a long and ugly
>> name.
>>
>>
>> On 26/10/2020 03.25, Tony V E via Std-Proposals wrote:
>>
>> I don't think you need unreachable.
>> *get_if should be enough. Unconditionally dereference the result.
>>
>> Sent from my BlackBerry portable Babbage Device
>> *From: *Justin Bassett via Std-Proposals
>> *Sent: *Sunday, October 25, 2020 9:16 PM
>> *To: *Std-Proposals
>> *Reply To: *std-proposals_at_[hidden]
>> *Cc: *Justin Bassett
>> *Subject: *Re: [std-proposals] std::as
>>
>> I'm glad to see that clang can also optimize this get_if access; it used
>> to be unable to do so. MSVC is also unable to optimize this when using
>> __assume (
>> https://docs.microsoft.com/en-us/cpp/intrinsics/assume?view=vs-2019 )
>> (which is the same as Clang's __builtin_assume()
>> https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume )
>> instead of __builtin_unreachable().
>>
>> In theory, a portable __builtin_unreachable() would be:
>>
>> [[noreturn]]
>> inline void unreachable() {} // basically, unconditionally trigger
>> undefined behavior
>>
>> In practice, only GCC seems to recognize this.
>>
>> --Justin Bassett
>>
>> On Sun, Oct 25, 2020 at 5:59 PM Ryan P. Nicholl via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>>
>>> [build] C:\Users\Ryan\rpnx-core\private\sources\all\test3.cpp(119,5): error C3861: '__builtin_unreachable': identifier not found [C:\Users\Ryan\rpnx-core\build\rpnx-core-test3.vcxproj]
>>>
>>> Great idea, except that __builtin_unreachable() is a GCC specific
>>> extension, and is not part of standard C++. (It would be nice to be able to
>>> do this in a cross platform way though! But that is for another discussion.)
>>>
>>> --
>>> Ryan P. Nicholl
>>> Tel: (678)-358-7765
>>> Personal Email: rnicholl_at_[hidden]
>>> Work Email: ryan.nicholl_at_[hidden]
>>> Tox:
>>> 52B3A61CDAF88BCC854F568933F071E3530600CDBA3D5354AADC9AD179575D68021AE959719D
>>>
>>>
>>> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>>> On Sunday, October 25, 2020 8:50 PM, Barry Revzin <
>>> barry.revzin_at_[hidden]> wrote:
>>>
>>>
>>>
>>> On Sun, Oct 25, 2020 at 7:41 PM Ryan P. Nicholl via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>>
>>>> I decided to implement a new class based on std::variant. I call it
>>>> "rpnx::derivator", but it's basically "allocating_variant". I tried to make
>>>> it as similar to std::variant as possible. When looking at this, I noticed
>>>> something weird about std::variant. There is no "zero overhead" way to get
>>>> the element contained by the variant, as std::get<I> checks for invalid
>>>> access and throws an exception if invalid. To solve this issue, I would
>>>> like to propose std::as, which works the same as std::get, but accessing
>>>> the wrong type is undefined behavior instead of throwing an exception.
>>>>
>>>> --
>>>> Ryan P. Nicholl
>>>> Tel: (678)-358-7765
>>>> Personal Email: rnicholl_at_[hidden]
>>>> Work Email: ryan.nicholl_at_[hidden]
>>>> Tox:
>>>> 52B3A61CDAF88BCC854F568933F071E3530600CDBA3D5354AADC9AD179575D68021AE959719D
>>>>
>>>
>>> You can achieve this by using std::get_if() and marking the nullptr case
>>> as unreachable. For example:
>>>
>>> auto f(std::variant<int, double>& v) -> int* {
>>> return std::get_if<int>(&v);
>>> }
>>>
>>> auto g(std::variant<int, double>& v) -> int* {
>>> auto p = std::get_if<int>(&v);
>>> if (not p) __builtin_unreachable();
>>> return p;
>>> }
>>>
>>> On -O1, f emits a check but g does not: https://godbolt.org/z/9G9fd5.
>>>
>>> Barry
>>>
>>>
>>> --
>>> 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 list run by std-proposals-owner@lists.isocpp.org

Standard Proposals Archives on Google Groups