C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Named Return Value Optimisation [[nrvo]]

From: Barry Revzin <barry.revzin_at_[hidden]>
Date: Tue, 10 Feb 2026 10:56:10 -0600
On Tue, Feb 10, 2026, 10:38 AM Jason McKesson via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Tue, Feb 10, 2026 at 11:25 AM Barry Revzin via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > On Tue, Feb 10, 2026, 10:13 AM David Brown via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> >> On 10/02/2026 16:21, Alejandro Colomar wrote:
> >> > Hi David,
> >> >
> >> > On 2026-02-10T15:47:12+0100, David Brown wrote:
> >> > [...]
> >> >>>> [[comp::attr]]
> >> >>>> Ignorable or non-ignorable according to the implementation (with
> the
> >> >>>> recommendation that it is ignorable by default but that the
> compiler provide
> >> >>>> a flag to make it non-ignorable).
> >> >>>>
> >> >>>> [[[comp::attr]]]
> >> >>>> Non-ignorable. If a compiler cannot support this in the manner
> intended by
> >> >>>> the "comp" compiler, it is a fatal error.
> >> >>>>
> >> >>>> [[(comp::attr)]]
> >> >>>> Ignorable. Compilers are encouraged to provide a warning if they
> are the
> >> >>>> owner of the "comp" namespace and do not recognise "attr".
> >> >>>>
> >> >>>> [[[comp1::attr1 || comp2::attr2 || ... ]]]
> >> >>>> Non-ignorable. Compilers must support and apply one of these
> attributes,
> >> >>>> but may choose which. If they cannot support any, it is a fatal
> error. For
> >> >>>> example, [[[gnu::always_inline || msvc::forceinline]]]
> >> >>>>
> >> >>
> >> >> You did not comment on this syntax, which I think is the most
> significant
> >> >> new idea in my post. Do you like this idea, or do you have a better
> >> >> alternative?
> >> >
> >> > That feature exists:
> >> >
> >> > #if __has_c_attribute(gnu::packed)
> >> > # define PACKED gnu::packed
> >> > #else if __has_c_attribute(foo::packed)
> >> > # define PACKED foo::packed
> >> > #else
> >> > # error "No support for a packed attribute"
> >> > #endif
> >> >
> >> > [[PACKED]] void f(void);
> >> >
> >> > I agree that || would be nice for this. I'd make it
> >> >
> >> > [[gnu::packed || foo::packed]]
> >> >
> >> > without a third '['
> >> >
> >>
> >> (The third [ was for consistency with user indication that the attribute
> >> should not be ignorable, but that's an orthogonal point.)
> >>
> >> >>
> >> >>>> [[(comp1::attr1 || comp2::attr2 || ... )]]
> >> >>>> The compiler can apply its choice of one of these attributes, but
> can ignore
> >> >>>> them all.
> >> >>>
> >> >>> I think it's a bad idea to allow programmers to decide about the
> >> >>> ignorability of language features. Ignorability of a feature
> should be
> >> >>> part of the feature itself. What would it mean to do
> >> >>>
> >> >>> [[(gnu::packed)]]
> >> >>>
> >> >>> ? That's an ABI-breaking attribute, and ignoring it will result in
> >> >>> bugs.
> >> >>>
> >> >>
> >> >> We can't legislate against programmers doing something stupid! And
> we
> >> >> certainly should not limit their abilities to make useful choices
> just
> >> >> because some people might do something silly - at least not when it
> requires
> >> >> an active choice such as this syntax requires. We should of course
> try to
> >> >> reduce the risk of accidental mistakes (which is a big reason, IMHO,
> that
> >> >> making "[[no_discard]]" ignorable is a terrible mistake - an
> accidental
> >> >> misspelling of a language feature should result in an error message,
> not be
> >> >> quietly discarded).
> >> >>
> >> >> But I think it would be fine for both the C++ standard and compiler
> >> >> documentation for namespace attributes to say that certain
> attributes cannot
> >> >> be ignored. If that applied to "gnu::packed", then
> "[[(gnu::packed)]]"
> >> >> would be an error. But programmers should be allowed to mark an
> attribute
> >> >> like "gnu::cold" as ignorable because it does not affect the
> semantics of
> >> >> the program in any way.
> >> >>
> >> >>> I prefer keeping all vendor attributes non-ignorable, and close the
> door
> >> >>> to ignorable vendor attributes. Then, if we want standard
> non-ignorable
> >> >>> ones, let's just specify a standard "vendor"; that could be the
> empty
> >> >>> prefix ::, or maybe std::.
> >> >>>
> >> >>
> >> >> There are lots of vendor attributes that can be used today, and that
> would
> >> >> be safe to ignore. I prefer to say that if an attribute is not
> ignorable
> >> >> (either because the user has used [[[ ]]], or because the it is
> documented
> >> >> as never ignorable) then it cannot be ignored by /any/ compiler.
> That
> >> >> requirement puts a lot of pressure on compiler implementations, and
> I think
> >> >> it is best to relieve that pressure by allowing attributes to be
> ignorable
> >> >> when the user knows that is safe.
> >> >
> >> > That feature exists:
> >> >
> >> > #if __has_c_attribute(gnu::cold)
> >> > # define COLD gnu::cold
> >> > #else
> >> > # define COLD
> >> > #endif
> >> >
> >> > [[COLD]] void f(void);
> >> >
> >> > I don't see a need for a new spelling.
> >> > I don't see a need to ignorable attributes.
> >> >
> >> >
> >> > Cheers,
> >> > Alex
> >> >
> >>
> >> While that is all true, it defeats the point of attributes (at least
> >> non-standard attributes) in the first place. After all, why support
> >> [[gnu::cold]] or [[msvc::cold_func]] (if that existed) format when you
> >> could have simply written :
> >>
> >> #if defined(__GNUC__)
> >> # define COLD __attribute__((cold))
> >> #elif defined(_MSC_VER)
> >> # define COLD _declspec(cold_func)
> >> #else
> >> # define COLD
> >> #endif
> >>
> >> COLD void f(void);
> >>
> >> Compiler-check conditional compilation and conditional macro definitions
> >> are horrible. Conditional compilation and macro definitions based on
> >> feature checks are marginally less horrible, but only marginally so.
> >> Both can be very useful, but you don't want to have to use them except
> >> in rare and unusual cases. It is far better to be able to write :
> >>
> >> [[gnu::cold, msvc::cold_func]] void f(void);
> >>
> >> and skip the pre-processor stuff.
> >
> >
> > This right here immediately gets straight to the issue. The only
> remotely plausible argument for there being any value in ignoring
> attributes is precisely that: to be able to write code like that and skip
> the preprocessor stuff.
> >
> > The problem is, it comes with it the very big cost that the compiler of
> course has no way to differentiate between the cases where you might
> conceivably want it to ignore... and the cases where you just wrote the
> wrong thing by accident and it's a bug. Even in this case where you might
> think is easy, just ignore vendored attributes in a different namespace,
> what if I wrote mvsc::meow instead of msvc::meow?
> >
> > As I wrote in my blog (
> https://brevzin.github.io/c++/2025/03/25/attributes/), a solution that
> would actually be useful here would be allow users to explicitly declare
> attributes they want "ignored" - which still isn't ignoring attributes (a
> design strategy that has clear negative value), simply explicitly declaring
> them to be no-ops. That would still require the preprocessor stuff, but
> only once per attribute, and the usage would have the good, macro-free
> syntax.
> >
> > Attributes are a great feature for adding new functionality without
> having to introduce new (uglier) keywords or grammar.
> >
> > Or, at least, they could be, if we just stop pre-emptively crippling
> them and pretending they're glorified comments.
>
> Why [[do]] we want [[to read]] code [[that]] looks [[like this]]? Why
> is this a good thing for the language?
>
> Attribute syntax is very eye-poking and makes code harder to read. Why
> do we want to proliferate this everywhere? If we need a way to make
> new keywords without impacting code, then we should add that as core
> functionality.
>

Attribute syntax is fine. Truly. It's fine. Of all the syntax problems this
language has, with its ambiguities and pointless freedoms, attribute syntax
is just not a problem (outside of being ambiguous with nested structured
bindings, which is annoying, nut you can't blame attributes for that).

Sure, you may not like the [[]]s, but this is purely subjective. Get over
it? It's obviously better than __attribute__((x)). It's also 50% better
than [[[x]]].


> People often talk about how the `co_await` and `co_return` keywords
> look bad. Seing `[[await]]` and `[[return]]` wouldn't be any better.
> Not only are they one keystroke longer, they poke you in the eye in a
> way that just text with underscores does not.


Nobody has ever argued, or would ever argue, that co_await shouldn't have
been a keyword.


> Attributes are only a "great feature for adding new functionality" if
> we ignore how they make the code look. I wasn't there for any of the
> conversations for attribute syntax, but wasn't one of the agreements
> made with the syntax that it *not* be used as a keyword replacement?
> Which is why it wasn't used for alignas, override, and final?
>

No. I already answered this. We got alignas(T) instead of [[align(T)]]
purely for C compatibility. Note that we also had to pick a worse word
because obviously can't use something like "align" as a keyword. But
attributes mean you don't have that problem.

[[override]] and [[final]] have even weaker justification than that, but we
couldn't make those full keywords either so we introduced contextual
keywords. This adds complexity to the language and grammar to... save some
square brackets?

I even disagree on the subjective nature of which looks better. If all of
the "decoration" looks the same, that's better. But right now some of our
decorations are attributes and others are contextual keywords or full
keywords, in a not-very-consistent way. Just vibes, basically.


> This feels a bit like a deal was worked out that people are now trying
> to renege on because it's convenient to do so.
>

I don't know what this means. The best time to fix a mistake was yesterday.
The second best time is today.

Keep in mind that the original attribute paper included thread_local as an
example of a good attribute (along with align).

Barry

>

Received on 2026-02-10 16:56:29