C++ Logo

std-proposals

Advanced search

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

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Tue, 10 Feb 2026 14:44:03 +0100
wt., 10 lut 2026 o 14:25 Alejandro Colomar
<une+cxx_std-proposals_at_[hidden]> napisał(a):
>
> Hi Marcin,
>
> On 2026-02-10T14:12:42+0100, Marcin Jaczewski wrote:
> > > > > alx_at_devuan:~/tmp$ cat nodiscard.c++
> > > > > [[nodiscard]] int f(void);
> > > > >
> > > > > int
> > > > > main(void)
> > > > > {
> > > > > typeof(int (void) ) *fp1;
> > > > > typeof(int (void)[[nodiscard]]) *fp2;
> > > > >
> > > > > fp1 = &f; // I would expect a diagnostic here.
> > > > > fp1();
> > > > >
> > > > > fp2 = &f;
> > > > > fp2();
> > > > > }
> > > > > alx_at_devuan:~/tmp$ g++ -S -Wall -Wextra nodiscard.c++
> > > > > nodiscard.c++: In function ‘int main()’:
> > > > > nodiscard.c++:7:38: warning: ‘nodiscard’ attribute can only be applied to functions or to class or enumeration types [-Wattributes]
> > > > > 7 | typeof(int (void)[[nodiscard]]) *fp2;
> > > > > | ^
>
> [...]
> > > No, that was not the point. The point is that the conversion in
> > > fp1 = &f;
> > > discards an attribute from the function type, and thus results in calls
> > > through that function pointer to not have a diagnostic when the return
> > > value is discarded. This is a hole in the rules.
> > >
> > > And the diagnostic you see in fp2 is in fact another hint that the
> > > design of [[nodiscard]] was bogus. That code should be accepted, and it
> > > should be the only way of storing a function pointer that holds &f. If
> > > that's not accepted, there is no way of using [[nodiscard]] safely.
> > >
> >
> > But what does this have to do with ignorability of attributes?
> > It's possible that you could not add the "not-ignorable" attribute there anyway.
> > ```
> > std::is_same<int, [[foo]] int>
> > ```
> > how C++ should handle it? even in case where it can't ignore this attribute.
> >
> > Only solution I see is that `fp1` itself should have `[[nodiscard]]`,
>
> Yes; it should be like fp2, and the attribute should be part of the type
> (and thus we should have no diagnostic in line 7).
>

I mean something diffrent, I word this wrongly.
I means that variable itself should have attribute like:

```
typeof(int (void)) *fp2 [[nodiscard]];
```

And this would fit the definition of `f` as its attribute is linked to
name not to its type.
And this will be fine in the current paradigm.

> > and this could be still ignorable.
>
> In part, this is a problem because either
>
> a) ignorability of attributes is the problem
> or
> b) [[nodiscard]] should not be ignorable, and should be replaced by a
> non-ignorable attribute.
>
> And if b) is chosen, then few very ignorable attributes would remain;
> so that ignorability of attributes would render attributes DoA. *The*
> truly ignorable attribute is [[maybe_unused]].
>
I can imagine many others that could work fine and be enforced by the compiler
but safely ignored if the compiler does not bother implementing them.

```
int* foo(int* b [[restrict(A,B)]], int* c [[restrict(C)]])
[[restrict(A,B,C)]]
{
     *b += 2;
     *c += 2;
     return *b < *c ? b : c;
}
```

Now if the compiler regonzie this attribute then he could only do 2
loads as pointers should not overlap.
If not, then it only generates less optimal code. if the programmer
lied then we get UB, same as `[[noreturn]]`.

>
> Cheers,
> Alex
>
> --
> <https://www.alejandro-colomar.es>

Received on 2026-02-10 13:44:18