Skip to content

<expected> Implement P0323R12 - #2643

Merged
Stephan T. Lavavej (StephanTLavavej) merged 29 commits into
microsoft:mainfrom
miscco:p0323-expected
May 24, 2022
Merged

Stephan T. Lavavej (StephanTLavavej) merged 29 commits into
microsoft:mainfrom
miscco:p0323-expected

Conversation

@miscco

@miscco Michael Schellenberger Costa (miscco) commented Apr 8, 2022

Copy link
Copy Markdown
Contributor

This implements <expected> that has been added by P0323R12.

I have also incorporated the changes from WG21-P2549.

I might have been a bit too strict with constraints.

Fixes #2529

Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Comment thread tests/std/tests/P0323R12_expected/test.cpp
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected
@miscco

This comment was marked as resolved.

Comment thread tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp Outdated
@AlexGuteniev

Copy link
Copy Markdown
Contributor

Have you considered empty object optimization for Empty unexpected class?

@miscco

Copy link
Copy Markdown
Contributor Author

Have you considered empty object optimization for Empty unexpected class?

You mean in the case expected<void, empty>?

@AlexGuteniev

Copy link
Copy Markdown
Contributor

Have you considered empty object optimization for Empty unexpected class?

You mean in the case expected<void, empty>?

Yes, and also expected<int, empty>.

@miscco

Copy link
Copy Markdown
Contributor Author

Have you considered empty object optimization for Empty unexpected class?

You mean in the case expected<void, empty>?

Yes, and also expected<int, empty>.

But the second one would not benefit from any empty base class optimization as we still have to allocate the value of T.

Also this essentially doubles the implementation size because we still have to do a lot of things. E.g. just because a type is empty does not mean its construction is trivial. So we would need to still keep a lot of the implementation.

I think if the maintainers really want to one could do it but the gains seem questionable.

@frederick-vs-ja

This comment was marked as resolved.

@miscco

This comment was marked as resolved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Video code review pending. 😸

Note to self: I still need to review <expected> starting at class expected, and the new test.cpp.

Comment thread stl/inc/yvals_core.h
Comment thread tests/std/tests/P0323R12_expected/env.lst
Comment thread tests/std/test.lst
Comment thread stl/inc/expected
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Thanks to cplusplus/draft#5381 ,
this shouldn't be marked as strengthened.
@StephanTLavavej

Copy link
Copy Markdown
Member

I've pushed one more change thanks to A. Jiang (@frederick-vs-ja)'s discovery in #2733 that cplusplus/draft#5381 has patched expected::error() to always be noexcept in the Standard (for both the primary template and void specialization).

@StephanTLavavej

Copy link
Copy Markdown
Member

Alex Guteniev (@AlexGuteniev) Thanks for raising the Empty Base Class Optimization question (in #2643 (comment) etc). I agree with Michael Schellenberger Costa (@miscco) that the implementation complexity would be high and the benefits would be minimal. Specifically, only the following cases would benefit:

  • expected<EmptyType, EmptyError>
  • expected<void, EmptyError>

In these cases, we could reduce the representation from 2 bytes (empty union followed by bool) to 1 byte (just the bool). Although it halves the space consumption, these scenarios seem quite unlikely. expected is useful when the error type contains a "reason". If it's an empty error type, it's just signaling its presence, so expected<Anything, EmptyError> provides little value over optional<Anything> (either you have the result or you don't), and expected<void, EmptyError> is basically a bool (did you succeed or fail - expected is slightly less ambiguous, but an enum class Result : bool { Failure, Success }; would avoid ambiguity.

Unlike empty allocators, empty comparators, empty function objects, etc. I think that the EBCO isn't worth the implementation complexity, throughput cost, and risk here.

@StephanTLavavej

Copy link
Copy Markdown
Member

I'm speculatively mirroring this to the MSVC-internal repo - further changes can be pushed, but please notify me.

"Standard Library Header Units: <expected> ICEs with Assertion failed: IsInClassDefn()"
@StephanTLavavej

Copy link
Copy Markdown
Member

I had to push an additional change to work around VSO-1543660 "Standard Library Header Units: <expected> ICEs with Assertion failed: IsInClassDefn()" by disabling the use of <expected> in that test. Additionally, I have renamed expected local variables to avoid shadowing when the test coverage is restored (interestingly, merely import <expected>; followed by such shadowing variables was causing the ICE).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed product code only. I'm now going to review the test code, after which I'll prepare changes for my comments if nobody has commented otherwise. (I'm trying to avoid digging through 175 comments to see if any of these have already been rejected, but I'll probably dig through anyway before I push.)

Comment thread stl/debugger/STL.natvis
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected
Comment thread stl/inc/expected
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected
Comment thread stl/inc/expected Outdated
Comment thread stl/inc/expected Outdated
@CaseyCarter Casey Carter (CaseyCarter) removed their assignment May 23, 2022
}
} // namespace test_expected

void test_reinit_regression() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have preferred to have this as part of the assignment tests but meh...

@StephanTLavavej

Copy link
Copy Markdown
Member

I have pushed a (hopefully final) commit to guard/optimize destruction as noticed by Michael Schellenberger Costa (@miscco), and to enable internal coverage for the header units test now that Cameron DaCamara (@cdacamar) has fixed the bug 🎉 🐞.

@StephanTLavavej
Stephan T. Lavavej (StephanTLavavej) merged commit b7ba3ad into microsoft:main May 24, 2022
@StephanTLavavej

Copy link
Copy Markdown
Member

Thanks for implementing this major C++23 feature - it's expected to be a popular one! 😹 😻 🎉

@miscco
Michael Schellenberger Costa (miscco) deleted the p0323-expected branch May 24, 2022 11:43
Igor Zhukov (fsb4000) pushed a commit to fsb4000/STL that referenced this pull request Aug 13, 2022
Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
Co-authored-by: Casey Carter <Casey@Carter.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cxx23 C++23 feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P0323R12 <expected>