[[nodiscard]]
in type alias declarationsDocument #: | P3245R0 |
Date: | 2024-04-16 |
Project: | Programming Language C++ |
Audience: |
Evolution Working Group Incubator |
Reply-to: |
Xavier Bonaventura (BMW) |
This paper proposes to allow the usage of [[nodiscard]]
to be used in type alias declarations in the same way that can be done
with [[deprecated]]
.
[[nodiscard]]
in types[[nodiscard]]
was initially proposed in [P0068R0] and [P0189R1] to be used in types and
functions. For types, it can be used in the following way:
struct [[nodiscard]] Error{
int code;
};
(){
MyError critical_callreturn {42};
}
int main(){
// Most compilers will issue diagnostics on the next call
// for any function that returns the MyError type
();
critical_call}
This allows users to notify the implementation that any function
returning a type Error
, its return
value should not be discarded silently.
There is one use case that is missing with the current allowed usage
of the [[nodiscard]]
attribute that would be useful.
Imagine an external library that defines a type
Error
that we want to use in our
library. Because this is conceptually an error type, in a safety
critical sytem you might be interested on having this type treated as
[[nodiscard]]
.
If the library already marks the type as [[nodiscard]]
then everything is good an you can use it directly or using an alias. If
that is not the case, then it is not so simple.
Intuitively we would put the [[nodiscard]]
attribute at the same place like it is allowed nowadays with [[deprecated]]
.
using MyError [[nodiscard]] = Error;
However, the attribute above will be ignored. The grammer allows the
attribute to be in such a position but it is not allowed by the [[nodiscard]]
attribute specification 9.12.9
[dcl.attr.nodiscard].
The proposal would be to allow the usage of [[nodiscard]]
in type aliases. This is already possible in a none standard way using
compiler annotations.
Before
|
After
|
---|---|
|
|
The main problem with the proposal above is that an alias declaration
is not a type. This is a big difference when trying to apply [[nodiscard]]
in comparison to [[deprecated]]
.
In the case of [[deprecated]]
,
the compiler can issue a warning in the moment that it sees the name in
the declaration. For the case of [[nodiscard]]
,
the compiler would have to keep this information additionally because
the alias is not a type.
In this section we will present the two possible solutions that could be done. I would like to get feedback from the committee which one is preferred.
[[nodiscard]]
informationThis option would require to remember if a function was seen with the alias or with the original type. This would mean that if the compiler has seen the function with the return alias, it should issue the warning when the return value is not used.
(int bar);
Error foo
(42); // No warning is issued`
foo
(int bar); // Same declaration like above due to Error and MyError being the same type
MyError foo
(42); // `[[nodiscard]] warning is issued` foo
Another direction could be considered is to introduce a mechanism to
introduce a type from another one. In this case, this would mean that
Error
and
MyError
would be two different
types, one that is [[nodiscard]]
and one that is not.
There is no wording yet, first the direction needs to be discussed. Depending on that the work on the wording will be done.
Thanks a lot to everyone that participated in the initial discussion
in Mattermost and during the Tokyo meeting. This allowed me to create
the first version of the paper already exposing the difference between
[[nodiscard]]
and [[deprecated]]
and exposing the challange with adding [[nodiscard]]
in type aliases.