Date: Fri, 3 Oct 2025 01:24:07 +0000 (UTC)
On Thursday, October 2, 2025 at 06:21:33 PM EDT, Jeremy Rifkin via Std-Proposals <std-proposals_at_[hidden]> wrote:
Hi,
What's the motivation for non-static thread-local class members?
What's the motivation for restricting an instance of a class to have
static storage duration?
Answer: Class versus per-instance member variable seems fully orthogonal to shared-by-all-threads versus thread-local, logically speaking. But a lot of complex scenarios arise if the thread lifetime is not contained within the lifetime an object that has thread_local variables as non-static members. Only allowing per-instance thread_local member variables avoids that complexity.
> If a class without this attribute has a non-static thread_local member variable, a warning should be issued
What would happen if a user tried to instantiate the class outside of
static storage, would that be an error? If so, this should be an error
not a warning. If the user can instantiate a class outside of static
storage, how do you envision that being implemented?
Answer: Yes, if a class is implicitly or explicitly (with the attribute) limited to static storage duration, it would be an error to declare an instance of it with some other storage duration. The class instance would need hidden information to locate the address of the variable within raw thread-local storage, akin to that needed to support virtuals. So, as with virtuals, a thread_local member variable would mean the class's default constructor was non-trivial. It would be reasonable to not allow member pointers to thread_local member variables, for simplicity's sake. Ditto for thread_local base classes.
How do you envision a compiler enforcing static lifetimes? How does
this interact with tools like placement new, unions, std::variant,
std::optional, ....?
Answer: Good point, this would not work well with placement new (even if the underlying storage had static duration). So maybe [[program_lifetime]] would be a better name for the class attribute, rather than [[static_duration]]. If X is an instance of a class C with the [[program_lifetime]] attribute, the storage for X must have static duration, the construction of X must be specified by the same definition that allocates the storage for X, and the destructor for X should only be called by std::exit(). This prohibits placement new from creating instances of classes with non-static thread_local member variables. Using such a class as the type of a union member variable would be pointless and should cause a diagnostic. Hopefully template parameter constraints can check for attributes of class parameters.
> This would have been nice to have for a class I'm currently working on.
How so?
Answer: in the rest of the paragraph that starts with that sentence. Did you want specific details?
Cheers,
Jeremy
On Thu, Oct 2, 2025 at 4:00 PM Walt Karas via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> I suggest allowing non-static thread_local member variables for classes, which would implicitly restrict instances of the class to have static storage duration.
>
> To support this change, I suggest adding the attribute [[static_duration]], for use in class declarations. If a class is declared with this attribute, all of its instances must have static duration. If a class without this attribute has a non-static thread_local member variable, a warning should be issued. (A warning should also be issued if the class has a base class or member variable whose type has implicit or explicit [[static_duration]].)
>
> This would have been nice to have for a class I'm currently working on. The only work-around I could to come up with was to make it a class template where the instantiations are singletons. The template takes a single (class) parameter. The only purpose of the template parameter is to create distinct instantiations, with distinct thread_local member variables.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Hi,
What's the motivation for non-static thread-local class members?
What's the motivation for restricting an instance of a class to have
static storage duration?
Answer: Class versus per-instance member variable seems fully orthogonal to shared-by-all-threads versus thread-local, logically speaking. But a lot of complex scenarios arise if the thread lifetime is not contained within the lifetime an object that has thread_local variables as non-static members. Only allowing per-instance thread_local member variables avoids that complexity.
> If a class without this attribute has a non-static thread_local member variable, a warning should be issued
What would happen if a user tried to instantiate the class outside of
static storage, would that be an error? If so, this should be an error
not a warning. If the user can instantiate a class outside of static
storage, how do you envision that being implemented?
Answer: Yes, if a class is implicitly or explicitly (with the attribute) limited to static storage duration, it would be an error to declare an instance of it with some other storage duration. The class instance would need hidden information to locate the address of the variable within raw thread-local storage, akin to that needed to support virtuals. So, as with virtuals, a thread_local member variable would mean the class's default constructor was non-trivial. It would be reasonable to not allow member pointers to thread_local member variables, for simplicity's sake. Ditto for thread_local base classes.
How do you envision a compiler enforcing static lifetimes? How does
this interact with tools like placement new, unions, std::variant,
std::optional, ....?
Answer: Good point, this would not work well with placement new (even if the underlying storage had static duration). So maybe [[program_lifetime]] would be a better name for the class attribute, rather than [[static_duration]]. If X is an instance of a class C with the [[program_lifetime]] attribute, the storage for X must have static duration, the construction of X must be specified by the same definition that allocates the storage for X, and the destructor for X should only be called by std::exit(). This prohibits placement new from creating instances of classes with non-static thread_local member variables. Using such a class as the type of a union member variable would be pointless and should cause a diagnostic. Hopefully template parameter constraints can check for attributes of class parameters.
> This would have been nice to have for a class I'm currently working on.
How so?
Answer: in the rest of the paragraph that starts with that sentence. Did you want specific details?
Cheers,
Jeremy
On Thu, Oct 2, 2025 at 4:00 PM Walt Karas via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> I suggest allowing non-static thread_local member variables for classes, which would implicitly restrict instances of the class to have static storage duration.
>
> To support this change, I suggest adding the attribute [[static_duration]], for use in class declarations. If a class is declared with this attribute, all of its instances must have static duration. If a class without this attribute has a non-static thread_local member variable, a warning should be issued. (A warning should also be issued if the class has a base class or member variable whose type has implicit or explicit [[static_duration]].)
>
> This would have been nice to have for a class I'm currently working on. The only work-around I could to come up with was to make it a class template where the instantiations are singletons. The template takes a single (class) parameter. The only purpose of the template parameter is to create distinct instantiations, with distinct thread_local member variables.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
-- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-10-03 01:24:34