Skip to content

[SUGGESTION] Static: Keyword with many meanings #322

Closed

Description

@AbhinavK00

In cpp, the keyword static is currently used at three different places:

  1. To declare objects with static lifetime
  2. To specify global variables with internal linkage
  3. To declare static members (data and functions) in classes

All of these 3 use cases are very different from one-another and therefore, using same keyword for all of them can be confusing, especially to beginners. Consider the following code:

static int a = 9;

auto foo (char t ){
    static float g = 42.0f;

}

The static in above declarations does different things (yes I know the variables behave kinda same but static does different things to them).

Therefore, I propose to divide the static keyword into 3 parts to address each use case differently.

  1. The first use case is the only one with radical change. Instead of using keyword static, we could agree on some different keyword that captures intent clearly in an unambigious way.
//cpp1 code

static int a = 0;

//cpp2 code
SOMETHING a := 0;     //not sure on position of keyword 

I think something like global can be used but put down your suggestions.

  1. This use case is already covered by anonymous namespaces in cpp and I think that's how it should be in cpp2. So no change here. Anonymous namespaces are a bit more verbose so if anyone has better idea, do suggest.

  2. This use case is partially already covered in cpp2. Static member functions are easily and distinguishably declared in cpp2 without the use of static keyword. So I'll be addressing the data member part only. The simple way would be to have a keyword. The real decision to make is whether it would be same as keyword chosen for 1) or a different one. A discussion on this topic would probably be needed so this currently is left unaddressed.

Note: I'd like to expand a bit on 1) to cover global variables too. They also have static lifetime. We can make it mandatory for global variables to be declared with some keyword (same as that would be decided for 1). Herb has plans to make global variables constexpr by default and is not sure if he'll even allow them or not. Having a keyword will capture attention of programmer and also be consistent with other static lifetime variables that would be declared.

These changes will make different things look different and do away with one small source of confusion to new programmers. This is a very small change so shouldn't be hard to implement.

Alternatives
We could also come up with different syntax for case 3) and leave case 1) as it is. That would be one option.

Activity

  1. JohelEGP commented on Apr 5, 2023

    @JohelEGP
    Contributor
    1. is already
    x : type = {
      f: () = { } // No `this` parameter, `static` member function.
    };
    
  2. AbhinavK00 commented on Apr 5, 2023

    @AbhinavK00
    Author

    Ohh, is there a way for static data members too?

  3. JohelEGP commented on Apr 5, 2023

    @JohelEGP
    Contributor

    Seems like that's not the case.

  4. msadeqhe commented on Apr 5, 2023

    @msadeqhe

    @AbhinavK00, so we have the following cases for static keyword in C++1:

    1. Local variables with static life-time

    I think this case isn't safe, because the life-time of a local variable will be extended without any obvious tracking.

    2. Global variables with internal linkage

    Anonymous namespaces are good enough as you have suggested:

    _: namespace = {
        variable := value;
    }
    

    or simply:

    _::variable := value;
    

    3. Static function members

    Yes, we already have it. This is the example from @JohelEGP:

    X: type = {
        func: () = { }
    }
    

    4. Static data members

    Using a keyword for this case seems natural as you have suggested:

    X: type = {
        KEYWORD variable := value;
    }
    

    Alternatively the following syntax can be used to eliminate KEYWORD like other cases don't have any additional keyword:

    X: type = {
     // X.variable := value;
        X::variable := value;
    }
    

    or this one:

    X: type = {
     // type.variable := value;
        type::variable := value;
    }
    

    In my opinion, type::variable is better than X::variable, because the type name doesn't have to be replicated multiple times.

  5. AbhinavK00 commented on Apr 5, 2023

    @AbhinavK00
    Author

    I think this would conflict with how we declare members outside of a class. The type::variable syntax would not, but it's close enough to be confused

  6. msadeqhe commented on Apr 5, 2023

    @msadeqhe

    I think this would conflict with how we declare members outside of a class.

    Would you provide an example? I don't know how it will conflict.

  7. AbhinavK00 commented on Apr 5, 2023

    @AbhinavK00
    Author

    Ah sorry, my bad. You're right, there would be no conflict.

  8. msadeqhe commented on Apr 5, 2023

    @msadeqhe

    No problem 😉

  9. leejy12 commented on Apr 8, 2023

    @leejy12
    1. Static data members
      Using a keyword for this case seems natural as you have suggested:
    X: type = {
       KEYWORD variable := value;
    }
    

    shared could be a possible candidate, as in this variable is "shared" by all instances of this type.

  10. orent commented on Apr 11, 2023

    @orent

    So which of these uses do you actually refer to as “static” in everyday speech? I know that I refer to 1 and 3 as “static” and 2 as “non exported symbol” or something like that. Use 2 is also the one that has a good alternative that highlights the fact that it is about symbol visibility rather than lifetime.

    No new keyword please. The keyword should match the terminology and the terminology should match that of C++ because Cpp2 shares the same underlying object model. Don’t fork the terminology.

  11. AbhinavK00 commented on May 14, 2023

    @AbhinavK00
    Author

    Closing now as not high priority, may reopen later.

  12. AbhinavK00 commented on Jun 28, 2023

    @AbhinavK00
    Author

    Another suggestion for use-case 2) would be to make global variables have internal linkage by default. As globals constants and globals constant expressions have internal linkage by default, it would be wise to do the same with global variables and have a keyword to specify external linkage instead.

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions