Skip to content

[SUGGESTION] Static members in types #522

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

Closed
MaxSagebaum opened this issue Jun 22, 2023 · 16 comments
Closed

[SUGGESTION] Static members in types #522

MaxSagebaum opened this issue Jun 22, 2023 · 16 comments

Comments

@MaxSagebaum
Copy link
Contributor

MaxSagebaum commented Jun 22, 2023

This is more of a question.

static members are currently not supported in cpp2. Is this due to the lack of time or some other considerations?

I would try to implement it as another modifier like e.g. public so that

t : type = {
 public static foo: int = 0;
}

main: () -> int = {
 t::foo += 1;
}

should work. I think t.foo += 1; would be better but this would be a quite large syntactic change in contrast to cpp1.

@AbhinavK00
Copy link

Sorry, but I fail to understand the above example. Shouldn't the member be inaccessible as it is declared private?
Also, maybe #322 mentions something similar.

@MaxSagebaum
Copy link
Contributor Author

Thanks for the hint. I wanted to spell it public.

@MaxSagebaum
Copy link
Contributor Author

Adapted the initial example.

@msadeqhe
Copy link

This issue is related to the topic.

should work. I think t.foo += 1; would be better but this would be a quite large syntactic change in contrast to cpp1.

The current plan for . vs :: is described in this comment. So t::foo is going to be the notation to access static members.

I would try to implement it as another modifier like e.g. public so that

Also syntactically it would be possible to declare static data members without any new keyword:

tt: type = {
    public type::foo: int = 0;
    // or
    public tt::foo: int = 0;
    // or
    public _::foo: int = 0;
    // or
    public ::foo: int = 0;
}

By the way, a keyword may improve its readability.

@JohelEGP
Copy link
Contributor

Cpp1 already let's you access static members with .: https://compiler-explorer.com/z/cW6vsYfGK.

I'm more concerned with the Cpp2 spelling of static data members.
Member functions naturally lower to Cpp1 static if they lack the this parameter.

Static data members is something that will be needed by the @enum metafunction.

@MaxSagebaum
Copy link
Contributor Author

This issue is related to the topic.

should work. I think t.foo += 1; would be better but this would be a quite large syntactic change in contrast to cpp1.

The current plan for . vs :: is described in this comment. So t::foo is going to be the notation to access static members.

I would try to implement it as another modifier like e.g. public so that

Also syntactically it would be possible to declare static data members without any new keyword:

tt: type = {
    public type::foo: int = 0;
    // or
    public tt::foo: int = 0;
    // or
    public _::foo: int = 0;
    // or
    public ::foo: int = 0;
}

By the way, a keyword may improve its readability.

I also think, that a keyword is more readable. If I had to choose from one of the four options. I think the fourth one would be my choice. But I would always prefer a keyword here.

Cpp1 already let's you access static members with .: https://compiler-explorer.com/z/cW6vsYfGK.

I'm more concerned with the Cpp2 spelling of static data members. Member functions naturally lower to Cpp1 static if they lack the this parameter.

Static data members is something that will be needed by the @enum metafunction.

That is correct but it is not possible without an actual instantiation of the type. https://compiler-explorer.com/z/Ks7eY1qKo
One option would be to declare something like std::declval but this might be in the region of undefined behavior.

@JohelEGP
Copy link
Contributor

That's OK.
I'm not suggesting to restrict access to .,
but to not restrict access to ::.
The linked comment is actually about unifying :: under ..

@MaxSagebaum
Copy link
Contributor Author

MaxSagebaum commented Jun 25, 2023

I'm not suggesting to restrict access to .,
but to not restrict access to ::.
The linked comment is actually about unifying :: under ..

That is what I also understood. I would propose to make the distinction in cpp2 the following:

  • :: access names and types
  • . access (static) members and functions

@JohelEGP
Copy link
Contributor

JohelEGP commented Aug 1, 2023

type::member i32; makes sense.
But how do you do it at namespace or local scope?

@msadeqhe
Copy link

msadeqhe commented Aug 2, 2023

At namespace scope, static global variables are inside unnamed namespace with internal linkage:

_::variable: i32;

main: () = {
    /// statements
}

At local scope, static local variables are devil. But if the plan is to support them, it's better for them to be visible in function declarations (no hidden stuff):

/// function: (_::variable: i32 = 10) = {
function: (static variable: i32 = 10) = {
    /// statements
}

main: () = {
    function();
}

They can be declared at the end of function parameter list, and they must have default value, and we cannot pass static arguments to the function.

@JohelEGP
Copy link
Contributor

JohelEGP commented Aug 2, 2023

At namespace scope, static global variables are inside unnamed namespace with internal linkage:

_::variable: i32;

Sounds brilliant if that statement is always true.
AFAIK, combining with other qualifiers messes with the semantics.
So I'm not sure whether it will hold as Cpp2 can author more Cpp1 qualifiers.

At local scope, static local variables are devil. But if the plan is to support them, it's better for them to be visible in function declarations (no hidden stuff):

/// function: (_::variable: i32 = 10) = {
function: (static variable: i32 = 10) = {

They can be declared at the end of function parameter list, and they must have default value, and we cannot pass static arguments to the function.

I don't disagree with "it's better for them to be visible in function declarations".
But putting them on the function parameter list
and yet being unable to pass them arguments
seems like a step back from explicit this parameters.

Regardless, if they're to be declared upfront,
I think they shouldn't need an initializer.
Instead, you should be able to initialize them in the body, where it happens most naturally.

FWIW, this formulation prohibits local statics of local type.

@JohelEGP
Copy link
Contributor

JohelEGP commented Aug 2, 2023

An alternative for locals is to overload __func__:

f: () = {
  __func__::var: type = init;
}

@hsutter
Copy link
Owner

hsutter commented Aug 29, 2023

I should reply to this: Cpp2 does already support 'static member functions' as type-scope functions that don't have this parameters.

But for static member data, that's global data, and I've been deliberately dragging my heels on all of:

  • global data
  • static local data
  • static class data

because they're globals, and mutable globals are something worth discouraging -- but they are sometimes useful, so my thought had been to require them to be hidden behind functions (e.g., Meyers singletons).

For now I'm allowing global data, but may require it to be constinit or similar.

End of quick brain dump!

@MaxSagebaum
Copy link
Contributor Author

Ok, so I will close this issue.

@MaxSagebaum MaxSagebaum closed this as not planned Won't fix, can't repro, duplicate, stale Aug 30, 2023
@JohelEGP
Copy link
Contributor

Then I wonder if we can get Cpp1 static constexpr data members in the form of a Cpp2 object alias.
x :== 0 -> static constexpr auto x{0};.

@hsutter
Copy link
Owner

hsutter commented Aug 30, 2023

Interesting idea, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants