C++ attributes
Date: 2022-12-18Last modified: 2024-11-02
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:62:11: warning: ignoring return value of ‘int get_zero()’, declared with attribute ‘nodiscard’ [-Wunused-result]
62 | get_zero();
| ~~~~~~~~^~
attributes.cpp:52:19: note: declared here
52 | [[nodiscard]] int get_zero() { return 0; }
| ^~~~~~~~
attributes.cpp:63:10: warning: ignoring return value of ‘int get_one()’, declared with attribute ‘nodiscard’: ‘Some custom message’ [-Wunused-result]
63 | 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:75:10: warning: ignoring returned value of type ‘ErrorType’, declared with attribute ‘nodiscard’ [-Wunused-result]
75 | get_two();
| ~~~~~~~^~
attributes.cpp:71:11: note: in call to ‘ErrorType get_two()’, declared here
71 | ErrorType get_two() { return {}; }
| ^~~~~~~
attributes.cpp:70:22: note: ‘ErrorType’ declared here
70 | struct [[nodiscard]] ErrorType {};
| ^~~~~~~~~
attributes.cpp: In function ‘void testLambda()’:
attributes.cpp:85:5: warning: ignoring return value of ‘testLambda()::<lambda()>’, declared with attribute ‘nodiscard’ [-Wunused-result]
85 | lm(); // would emit a warning
| ~~^~
attributes.cpp:84:13: note: declared here
84 | auto lm = [] [[nodiscard]] () -> int { return 42; };
| ^
attributes.cpp: In constructor ‘FDHolder::FDHolder(int)’:
attributes.cpp:93:30: warning: unused parameter ‘FD’ [-Wunused-parameter]
93 | [[nodiscard]] FDHolder(int FD){};
| ~~~~^~
attributes.cpp: In function ‘void testConstructor()’:
attributes.cpp:99:15: warning: ignoring return value of ‘FDHolder::FDHolder(int)’, declared with attribute ‘nodiscard’ [-Wunused-result]
99 | FDHolder{42}; // warning
| ^
attributes.cpp:93:17: note: declared here
93 | [[nodiscard]] FDHolder(int FD){};
| ^~~~~~~~
attributes.cpp: In function ‘void testNoExcept()’:
attributes.cpp:115:3: warning: ‘throw’ will always call ‘terminate’ [-Wterminate]
115 | throw 42;
| ^~~~~~~~