C++ attributes
Date: 2022-12-18Last modified: 2023-03-16

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:62:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
get_zero();
^~~~~~~~
attributes.cpp:63:3: warning: ignoring return value of function declared with 'nodiscard' attribute: Some custom message [-Wunused-result]
get_one();
^~~~~~~
attributes.cpp:75:3: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
get_two();
^~~~~~~
attributes.cpp:84:16: warning: an attribute specifier sequence in this position is a C++2b extension [-Wc++2b-extensions]
auto lm = [] [[nodiscard]] () -> int { return 42; };
^
attributes.cpp:85:5: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
lm(); // would emit a warning
~~^~
attributes.cpp:93:30: warning: unused parameter 'FD' [-Wunused-parameter]
[[nodiscard]] FDHolder(int FD){};
^
attributes.cpp:99:3: warning: ignoring temporary created by a constructor declared with 'nodiscard' attribute [-Wunused-value]
FDHolder{42}; // warning
^~~~~~~~~~~~
attributes.cpp:115:3: warning: 'testNoExcept' has a non-throwing exception specification but can still throw [-Wexceptions]
throw 42;
^
attributes.cpp:112:6: note: function declared non-throwing here
void testNoExcept() noexcept {
^ ~~~~~~~~
8 warnings generated.