#include <iostream>
#include <memory>
class A
{
public:
static [[nodiscard]] std::unique_ptr<A> create();
virtual int get_version() = 0;
virtual ~A() = default;
};
class B : public A
{
public:
[[nodiscard]] int get_version() override
{
return 20;
}
};
std::unique_ptr<A>
A::create()
{
return std::make_unique<B>();
}
int main()
{
auto a = A::create();
[[maybe_unused]] int v = a->get_version();
}
I tried to use [[nodiscard]]
to not allow ignoring the return value of A::create()
.
But, I get different compilation output in GCC and Clang.
Tried with
- GCC: 8.5
- Clang: 15.0.0
- Compilation options: -O3 -std=c 17
- Godbolt link: https://godbolt.org/z/qa7TfcK9f
GCC:
<source>:7:12: warning: attribute ignored [-Wattributes]
static [[nodiscard]] std::unique_ptr<A> create();
^
<source>:7:12: note: an attribute that appertains to a type-specifier is ignored
ASM generation compiler returned: 0
<source>:7:12: warning: attribute ignored [-Wattributes]
static [[nodiscard]] std::unique_ptr<A> create();
^
<source>:7:12: note: an attribute that appertains to a type-specifier is ignored
Execution build compiler returned: 0
Program returned: 0
Clang:
<source>:7:14: error: 'nodiscard' attribute cannot be applied to types
static [[nodiscard]] std::unique_ptr<A> create();
^
1 error generated.
ASM generation compiler returned: 1
<source>:7:14: error: 'nodiscard' attribute cannot be applied to types
static [[nodiscard]] std::unique_ptr<A> create();
^
1 error generated.
Execution build compiler returned: 1
Am I doing something wrong? And why does these compilers have different behavior?
This code works with MSVC v19.33 properly without any errors or warnings: https://godbolt.org/z/dWsv4jTo5
CodePudding user response:
You can see here https://eel.is/c draft/class.mem#general that the attribute can only appear first in a member declaration. Hence this
static [[nodiscard]] std::unique_ptr<A> create();
is wrong. And should be
[[nodiscard]] static std::unique_ptr<A> create();
Your code has a typo.
Newever versions of gcc report a more clear error:
source>:7:12: error: standard attributes in middle of decl-specifiers
7 | static [[nodiscard]] std::unique_ptr<A> create();
| ^
<source>:7:12: note: standard attributes must precede the decl-specifiers to apply to the declaration, or follow them to apply to the type
<source>:7:12: warning: attribute ignored [-Wattributes]
<source>:7:12: note: an attribute that appertains to a type-specifier is ignored
Actually I do not know if it has to be reported as error or if a warning is ok too. I don't think it relly matters, because you need to fix it anyhow, and unless you ignore warnings you cannot miss it. MSCV not diagnosing the issue is not nice. However, you should also keep in mind that [[nodiscard]]
like similar attributes merely encourage the compiler to issue a warning. There is no gurantee to get a warning when it is discarded.