Skip to content

feat: add _type-id_ production for decltype #921

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

Merged
merged 2 commits into from
Oct 4, 2024

Conversation

JohelEGP
Copy link
Contributor

@JohelEGP JohelEGP commented Jan 8, 2024

No description provided.

@hsutter
Copy link
Owner

hsutter commented Sep 25, 2024

Thanks! Sorry for the lag.

It seems like the motivation overlaps with the later discussion in #714 which starts to add decltype(auto), though only for single-expression bodies.

Perhaps this and #876 are underscoring that there need to be three (not two) return styles, which has come up in my mind several times before:

  • by value, which is currently default or can be explicitly spelled move... maybe this should be spelled copy?
  • by reference to support string::operator[] use cases, which is currently spelled forward... maybe this should be spelled something like ref (*)?
  • by perfect backwarding, which currently has no spelling but the natural name would be forward and lower to decltype(auto)?

What do you think? That would bottom out on both #714 and #876, and be instead of this PR?


(*) There's a longer story here: For many years, the best candidate names I've considered for "in/out" parameters are inout and ref.

  • ref has the advantage of symmetry: The same word could be directly used for both parameters and returns that are lvalue references. However, a major disadvantage is that it's about "how" to pass the parameter, not "what" the parameter is for.
  • inout has the (IMO compelling) advantage of "what" not "how": Plus it connotes explicit data-flow. It's just perfect for parameters IMO. However, inout doesn't feel quite right as a return from string::operator[].

I liked the idea of trying to make the return styles be a subset of the parameter styles, but maybe it's time to reconsider that it doesn't quite work. If we keep inout for lvalue reference parameters, what's the right "what" word for what string::operator[] returns... what is a "what" word that describes what the callee/caller wants to do with it?

Edited to add: Brainstorming... loan? lend? show? share? actual? original? or maybe qualifier_forward?

Naming is hard.

@JohelEGP
Copy link
Contributor Author

That comment seems more appropriate for #876.
General support for decltype as a type-id is desirable (this PR),
even if we reject -> decltype(auto) in favor of -> forward as you suggest, which I like.

#714's gotten long and contentious (I'm a fan of the main branch's :(x) x standing for :(x) -> _ = x).
Can I have some specific links to comments?

Since main is only missing decltype(auto) for perfect backwarding,
I imagine this is about enhancing :(x) x to somehow specify x to return by something other than by value.

  • by value, which is currently default or can be explicitly spelled move... maybe this should be spelled copy?

    • by reference to support string::operator[] use cases, which is currently spelled forward... maybe this should be spelled something like ref (*)?

    • by perfect backwarding, which currently has no spelling but the natural name would be forward and lower to decltype(auto)?

What do you think?

  • Changing the default's spelling from -> move to -> copy makes sense.
  • -> forward does indeed work well for perfect backwarding.

As for string::operator[], how about this?

string: type = {
  operator[]: (this) -> this char; // Returns a `char` reference in the `in this` value, naturally by `const`.
  operator[]: (inout this) -> this char; // Returns a `char` reference in the `inout this` value, naturally non-`const`.
}

That also documents the provenance.
For a more global reach, continue using the concrete -> forward (https://cpp2.godbolt.org/z/f181eG3Wz):

get_cout: () -> forward std::ostream = std::cout;

@MaxSagebaum
Copy link
Contributor

string: type = {
  operator[]: (this) -> this char; // Returns a `char` reference in the `in this` value, naturally by `const`.
  operator[]: (inout this) -> this char; // Returns a `char` reference in the `inout this` value, naturally non-`const`.
}

It is a good idea, but could be easily miss read as a function returning this or a function which returns two arguments.

@JohelEGP
Copy link
Contributor Author

Yeah. So why not continue using concrete -> forward if it's still a thing?

string: type = {
  operator[]: (this) -> forward const char;
  operator[]: (inout this) -> forward char;
}

@JohelEGP
Copy link
Contributor Author

* **by reference** to support `string::operator[]` use cases, which is currently spelled `forward`... maybe this should be spelled something like `ref` (*)?

I'm fine with keeping (concrete) -> forward for return by reference.
By virtue of Cpp2 being safe, that will by returning a non-local object.

@hsutter
Copy link
Owner

hsutter commented Sep 25, 2024

That comment seems more appropriate for #876

Good point, I'll move replies there.

General support for decltype as a type-id is desirable (this PR),

OK. Do you want to refresh/rebase this branch for me to review?

Also, do we want specifically decltype semantics? Or decltype + remove_cvref semantics (which I would call typeof)?

@JohelEGP
Copy link
Contributor Author

General support for decltype as a type-id is desirable (this PR),

OK. Do you want to refresh/rebase this branch for me to review?

I'll do that.

Also, do we want specifically decltype semantics? Or decltype + remove_cvref semantics (which I would call typeof)?

I was assuming we'd be using the same decltype keyword as C++, in which case, it'd have the same behavior.
Were you perhaps thinking of spelling it -> forward(expression)?

-> decltype(expression) returns have their place in generic code.
There may be use cases where something like -> typeof(expression) might be more appropriate.
Do you think we should also allow that? Unfortunately, it seems it doesn't already work, due to the parentheses.

@hsutter
Copy link
Owner

hsutter commented Oct 3, 2024

What I was thinking was to make this PR exclusively about adding decltype() as a type-id. And not allow auto in there (auto is not a Cpp2 thing currently).

I have separate plans for the return type: To make Cpp1 -> decltype(auto) and -> auto&& spelled as Cpp2 -> forward and -> forward_ref.

@JohelEGP
Copy link
Contributor Author

JohelEGP commented Oct 3, 2024

OK. I'll just have to reject a decltype as the type-id of return-list.

@hsutter
Copy link
Owner

hsutter commented Oct 3, 2024

Great. I'll watch for conflicts to be resolved, then I'll take a review pass. Thanks!

@JohelEGP
Copy link
Contributor Author

JohelEGP commented Oct 3, 2024

I just noticed that we also don't have decltype(auto) for variables.
The best approximation are forward: _ parameters: https://cpp2.godbolt.org/z/MKsocP6bb.

@hsutter hsutter removed the question - further information requested Further information is requested label Oct 4, 2024
@hsutter hsutter merged commit 4f399a7 into hsutter:main Oct 4, 2024
20 of 29 checks passed
@JohelEGP JohelEGP deleted the decltype_type_id branch October 4, 2024 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants