C++ attributes
C++ attributes nodiscard noreturn assume noexcept
Table of contents
Brief
[[nodiscard]][[noreturn]][[carries_dependency]][[assume]]noexcept
Attribute [[nodiscard]]
- Used to indicate when it is an error to ignore a return value from a function
- Can be applied to constructors as of C++20
- Can have a message to explain the error
[[nodiscard("Lock objects should never be discarted")]]
- Should be used extensively.
- Any non-mutating (getter/accessor/{eonse) function should be `[[nodiscard]]
cos()vector::insert(): Return an iterator that points to the first of the newly inserted elements.- Can be checked / enforced with static analysis
☢
Warning
filename.cpp:46:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
Function
[[nodiscard]] int get_zero() { return 0; }
[[nodiscard("Some custom message")]] int get_one() { return 1; }
[[nodiscard("XXX find me XXX on warning messages")]] int unused_function() { return -1; }
void testFunction() {
fmt::print(stderr, "testFunction()\n");
get_zero();
get_one();
}
Types
struct [[nodiscard]] ErrorType {};
ErrorType get_two() { return {}; }
void testType() {
fmt::print(stderr, "testType()\n");
get_two();
}
Lambda
void testLambda() {
fmt::print(stderr, "testLambda()\n");
auto lm = [] [[nodiscard]] () -> int { return 42; };
lm(); // would emit a warning
}
Constructor
struct FDHolder {
[[nodiscard]] FDHolder(int FD) {};
FDHolder() {};
};
void testConstructor() {
fmt::print(stderr, "testConstructor()\n");
FDHolder{42}; // warning
FDHolder h{42}; // constructed object not discarded, no warning
FDHolder{}; // defalt constructed, no warning
}
noexcept
noexcept notifies the user (and compiler) that a function may not
throw an exception. If an exception is thrown from that function,
terminate MUST be called.
void testNoExcept() noexcept {
fmt::print(stderr, "testNoExcept()\n");
// required to terminate the program
throw 42;
}
try {
testFunction();
testLambda();
testConstructor();
testNoExcept(); // terminate is called here
testFunction(); // never called
} catch (...) {
// catch is irrelevant, `terminate` is called
}
fmt::print(stderr, "End of program\n");
Error output
testFunction()
testLambda()
testConstructor()
testNoExcept()
terminate called after throwing an instance of 'int'
Compilation output
attributes.cpp: In function ‘void testFunction()’:
attributes.cpp:60:11: warning: ignoring return value of ‘int get_zero()’, declared with attribute ‘nodiscard’ [-Wunused-result]
60 | get_zero();
| ~~~~~~~~^~
attributes.cpp:52:19: note: declared here
52 | [[nodiscard]] int get_zero() { return 0; }
| ^~~~~~~~
attributes.cpp:61:10: warning: ignoring return value of ‘int get_one()’, declared with attribute ‘nodiscard’: ‘Some custom message’ [-Wunused-result]
61 | get_one();
| ~~~~~~~^~
attributes.cpp:54:42: note: declared here
54 | [[nodiscard("Some custom message")]] int get_one() { return 1; }
| ^~~~~~~
attributes.cpp: In function ‘void testType()’:
attributes.cpp:73:10: warning: ignoring returned value of type ‘ErrorType’, declared with attribute ‘nodiscard’ [-Wunused-result]
73 | get_two();
| ~~~~~~~^~
attributes.cpp:69:11: note: in call to ‘ErrorType get_two()’, declared here
69 | ErrorType get_two() { return {}; }
| ^~~~~~~
attributes.cpp:68:22: note: ‘ErrorType’ declared here
68 | struct [[nodiscard]] ErrorType {};
| ^~~~~~~~~
attributes.cpp: In function ‘void testLambda()’:
attributes.cpp:83:5: warning: ignoring return value of ‘testLambda()::<lambda()>’, declared with attribute ‘nodiscard’ [-Wunused-result]
83 | lm(); // would emit a warning
| ~~^~
attributes.cpp:82:13: note: declared here
82 | auto lm = [] [[nodiscard]] () -> int { return 42; };
| ^
attributes.cpp: In constructor ‘FDHolder::FDHolder(int)’:
attributes.cpp:91:30: warning: unused parameter ‘FD’ [-Wunused-parameter]
91 | [[nodiscard]] FDHolder(int FD) {};
| ~~~~^~
attributes.cpp: In function ‘void testConstructor()’:
attributes.cpp:97:15: warning: ignoring return value of ‘FDHolder::FDHolder(int)’, declared with attribute ‘nodiscard’ [-Wunused-result]
97 | FDHolder{42}; // warning
| ^
attributes.cpp:91:17: note: declared here
91 | [[nodiscard]] FDHolder(int FD) {};
| ^~~~~~~~
attributes.cpp: In function ‘void testNoExcept()’:
attributes.cpp:113:3: warning: ‘throw’ will always call ‘terminate’ [-Wterminate]
113 | throw 42;
| ^~~~~~~~