Date: Sun, 16 Nov 2025 17:11:26 -0500
On Fri, Nov 14, 2025 at 2:26 PM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:
> On Fri, Nov 14, 2025 at 9:38 AM Frederick Virchanza Gotham via
> Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>> [...] I've implemented "std::contains_mutable". Here's my compiler patch
>> for GNU g++:
>>
>> https://github.com/healytpk/gcc-thomas-healy/commit/tag_contains_mutable
>>
>
> [...] If there is a rationale for adding something like
> `std::contains_mutable(_member)` to the Standard, it would be because
> compiler vendors "already have to do it anyway," i.e. the same rationale we
> saw for std::is_implicit_lifetime, std::is_scoped_enum,
> std::reference_converts_from_temporary, etc. These are properties that
> affect what the front-end and/or back-end allow you to do with a type, so,
> every compiler must have a way to check for them already. All the
> type-trait does is *expose that way* to the end-user.
>
> The property of "(recursively) containing mutable members" is needed by
> the compiler in order safely to implement P2752 static storage for braced
> initializers
> <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2752r3.html>.
> This was pointed out by Hubert Tong; see §4 of that paper.
> The example is:
> // https://godbolt.org/z/j8cxfbo39
>
Not long after sending this, I realized that of course this property is
also needed to implement const global variables in general.
// https://godbolt.org/z/hdG16nqKs
struct C {
int i_;
};
struct M {
mutable int i_;
};
void fc(const C&);
void fm(const M&);
void withC() {
static constexpr C c = {42};
fc(c);
}
void withM() {
static constexpr M m = {42};
fm(m);
}
Again, notice the difference in codegen between withC()::c and withM()::m —
the former can go into rodata, whereas the latter cannot. Both GCC and
Clang understand this. So Clang already has this notion, too, somewhere, if
you can find it.
So, GCC *[and, he now adds, Clang too]* clearly already has a notion of
> "contains mutable members." Your type-trait should just expose that notion
> to the end-user, and as such, it's a *plausible* candidate to propose for
> standardization, IMO.
> However, I took a quick look at your GCC patch, and it looks to me as if
> you reinvented the wheel there. Why is your patch not (in spirit) a
> one-liner? Why are you manually iterating over members and bases? This is
> not the implementation I would expect to see, given the above rationale.
>
> It is possible that GCC's existing "contains mutable" logic is not yet
> factored out into a simple function (because I bet it's used in only one
> place right now). *[Nope, it must be used in several places. I'd be
> surprised to find it open-coded in all those places.]* In that case,
> instead of merely *finding and calling* that function, you'll need to *factor
> out* that function as part of your patch. I have no special knowledge or
> connections re GCC, but I'd imagine that a well-written such patch might
> actually be accepted upstream, if accompanied by a rationale such as I've
> given here.
>
–Arthur
wrote:
> On Fri, Nov 14, 2025 at 9:38 AM Frederick Virchanza Gotham via
> Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>> [...] I've implemented "std::contains_mutable". Here's my compiler patch
>> for GNU g++:
>>
>> https://github.com/healytpk/gcc-thomas-healy/commit/tag_contains_mutable
>>
>
> [...] If there is a rationale for adding something like
> `std::contains_mutable(_member)` to the Standard, it would be because
> compiler vendors "already have to do it anyway," i.e. the same rationale we
> saw for std::is_implicit_lifetime, std::is_scoped_enum,
> std::reference_converts_from_temporary, etc. These are properties that
> affect what the front-end and/or back-end allow you to do with a type, so,
> every compiler must have a way to check for them already. All the
> type-trait does is *expose that way* to the end-user.
>
> The property of "(recursively) containing mutable members" is needed by
> the compiler in order safely to implement P2752 static storage for braced
> initializers
> <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2752r3.html>.
> This was pointed out by Hubert Tong; see §4 of that paper.
> The example is:
> // https://godbolt.org/z/j8cxfbo39
>
Not long after sending this, I realized that of course this property is
also needed to implement const global variables in general.
// https://godbolt.org/z/hdG16nqKs
struct C {
int i_;
};
struct M {
mutable int i_;
};
void fc(const C&);
void fm(const M&);
void withC() {
static constexpr C c = {42};
fc(c);
}
void withM() {
static constexpr M m = {42};
fm(m);
}
Again, notice the difference in codegen between withC()::c and withM()::m —
the former can go into rodata, whereas the latter cannot. Both GCC and
Clang understand this. So Clang already has this notion, too, somewhere, if
you can find it.
So, GCC *[and, he now adds, Clang too]* clearly already has a notion of
> "contains mutable members." Your type-trait should just expose that notion
> to the end-user, and as such, it's a *plausible* candidate to propose for
> standardization, IMO.
> However, I took a quick look at your GCC patch, and it looks to me as if
> you reinvented the wheel there. Why is your patch not (in spirit) a
> one-liner? Why are you manually iterating over members and bases? This is
> not the implementation I would expect to see, given the above rationale.
>
> It is possible that GCC's existing "contains mutable" logic is not yet
> factored out into a simple function (because I bet it's used in only one
> place right now). *[Nope, it must be used in several places. I'd be
> surprised to find it open-coded in all those places.]* In that case,
> instead of merely *finding and calling* that function, you'll need to *factor
> out* that function as part of your patch. I have no special knowledge or
> connections re GCC, but I'd imagine that a well-written such patch might
> actually be accepted upstream, if accompanied by a rationale such as I've
> given here.
>
–Arthur
Received on 2025-11-16 22:11:43
