Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P0323R12 std::expected #5276

Merged
merged 2 commits into from Feb 19, 2022
Merged

P0323R12 std::expected #5276

merged 2 commits into from Feb 19, 2022

Conversation

jensmaurer
Copy link
Member

  • Introduce "General" subclauses to avoid hanging paragraphs.
  • Introduce "Returns: *this" to avoid duplication.

Fixes #5261
Fixes cplusplus/papers#254

@jensmaurer jensmaurer added this to the post-2022-02 milestone Feb 9, 2022
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
Comment on lines +6652 to +6654
constexpr E&& value() && noexcept;
constexpr const E&& value() const&& noexcept;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
constexpr E&& value() && noexcept;
constexpr const E&& value() const&& noexcept;
constexpr const E&& value() const&& noexcept;
constexpr E&& value() && noexcept;

Should we keep this consistent with the general synopsis? (Also many other specifications are inconsistent too, like expected<T, E>::operator*(), bad_excepted_access<E>::error() etc.. If we fix this, we may as well fix the others too...)

Another way is to fix the general synopsis to be consistent with const&-&-&&-const&& order, with the additional benefit of be consistent with optional<T>::operator*() and optional<T>::value() (these two are the only case in stdlib where all 4 member function qualifiers overload appears currently). However I don't feel this order is nature than, say const&-&-const&&-&&. (Maybe we should set a new standard for a natural overload order? i.e. fix optional<T> to use const&-&-const&&-&& order too?)

Copy link
Member

Choose a reason for hiding this comment

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

I thought we usually have a non-const overload first, then const. That's what we do or begin() and end() in containers and strings, but then we have operator[] and front() and back() in basic_string where the const overload is first.

I agree we should probably be globally consistent (and IMHO the most natural order is either & const& && const&& or & && const& const&&) but we are already badly inconsistent.

Making this member consistent with the class synopsis makes sense. I don't think we need to rearrange the synopsis for consistency given that we don't have any real consistency.

Choose a reason for hiding this comment

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

Just as another datapoint: std::get for array, pair, tuple and variant comes in 4 flavors, too. array, tuple and variant use the &, &&, const&, const&& order, while pair uses &, const&, &&, const&&.

Thus I agree that only consistency with the general synopsis makes sense here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's just float the idea: is there any interest inside WG21 editor team for an editorial PR that makes every member function (overloaded only by qualifiers) in stdlib to become a consistent order (presumably &-const&-&&-const&&/always no-quals before const, since the tradition is to specify first two in a group and next two (often need additional std::move) in other), and thus we can commit to future consistency in new proposals?

If there is interest I may be able to commit time to make a PR when I have spare time.

Copy link
Member Author

Choose a reason for hiding this comment

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

Can we switch the entire thing to explicit object parameters and avoid the question entirely?
@jwakely , is that an ABI break of concern for the templates we talk about here?

Copy link
Member

@jwakely jwakely Feb 11, 2022

Choose a reason for hiding this comment

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

We can and should do it for expected (and that's been suggested previously). We could do it for optional::value and I don't see why it would be an ABI break. Users can't rely on specific signatures for member functions, as per [member.functions], so even if it is a break, an implementation could retain four separate overloads if required for ABI compat.

We can't do it for std::get because those aren't members.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think if the calling convention of

struct S {
    void fun(int) const &;
}

and

struct S {
    static void fun(const S&, int);
}

is completely the same (which it seems to be, testing on godbolt), then there shouldn't be an ABI break (except that the mangled name is different, and this can be solved by providing aliases).

However a possible scenario is that if we provide it as

template<typename E>
struct unexpected {
    constexpr decltype(auto) value(this auto&& self) noexcept {return std::forward<decltype(self)>(self).unex;}
}

then, I think that for types derivated from unexpected<E> this can be an ABI break: the calling convention between calling unexpected<E>::value() const & (ordinary member) and calling unexpected<E>::value<const Derived&>(this const Derived&) (deducing this) can be different, because the former you need a cast from const Derived& to const unexpected<E>& (which can be not nop, in case of multiple inheritance), and the latter due to template you do not need any cast. A testing is done here.

Copy link
Member

Choose a reason for hiding this comment

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

There cannot possibly be an ABI break for std::unexpected because it doesn't exist in any implementation yet.

And anyway, if the mangled name is different (and it is) then it doesn't matter whether the calling convention is the same or not. It's a different symbol and existing callers of the old symbol (that already have an instantiation of the old definition) cannot be affected by the addition of a new symbol. The only potential problem is if users are relying on explicit instantiations of std::optional, but whether that is supported or not is unspecified and QoI.

But that's all off-topic for an editorial PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, yeah, sorry I misunderstand the ABI break scenario… Then that’s great and so think we can change optional/expected to explicit this without any breakage.

Anyways, this needs a new proposal to change and is outside the scope. I think for this PR the only thing we need to done is to change every specification order to match the general synopsis…

Copy link
Member

@jwakely jwakely left a comment

Choose a reason for hiding this comment

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

All of @Mick235711's suggestions look correct.

Copy link
Contributor

@Mick235711 Mick235711 left a comment

Choose a reason for hiding this comment

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

(I think I found all the \pnum issues... sorry if I'm wrong or overshoot anything, since I used LaTeX but not very familiar with C++ draft's heavily-customized flavor)

source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
@jensmaurer jensmaurer force-pushed the motions-2022-02-lwg-2 branch 2 times, most recently from f2d38a0 to 0edf6b6 Compare February 11, 2022 11:36
Copy link
Contributor

@JohelEGP JohelEGP left a comment

Choose a reason for hiding this comment

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

How about indexing void expected as expected<void>? This should reduce confusion and back-and-forth, guess-the-correct-one when looking up members from the index.

source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Show resolved Hide resolved
@jensmaurer
Copy link
Member Author

How about indexing void expected as expected? This should reduce confusion and back-and-forth, guess-the-correct-one when looking up members from the index.

Do we have an existing practice in that area?

@JohelEGP
Copy link
Contributor

I know there are some for atomics:

1644606246
1644606190
1644606194
1644606197
1644606203
1644606209
1644606214
1644606220
1644606228
1644606230
1644606235

@jensmaurer
Copy link
Member Author

Indexing for expected<void> is now fixed.

source/utilities.tex Outdated Show resolved Hide resolved
source/utilities.tex Outdated Show resolved Hide resolved
- Introduce "General" subclauses to avoid hanging paragraphs.
- Introduce "Returns: *this" to avoid duplication.
- Add missing "friend" from item description of expected::operator==.
Includes fixing a misspelled function name in [expected.object.ctor]
and misspelled parameters in [expected.un.ctor].

Changes "This subclause" to "Subclause <ref>" to accommodate the
additional sectioning that was introduced to avoid hanging paragraphs.
@tkoeppe tkoeppe merged commit 63b9a25 into main Feb 19, 2022
@jensmaurer jensmaurer deleted the motions-2022-02-lwg-2 branch July 29, 2022 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[2022-02 LWG Motion 2] P0323R12 std::expected P0323 std::expected
6 participants