Quick Links: |
Provide a macro for warning about ignored function results. More...
BSLA_NODISCARD | warn if annotated function result is not used |
BSLA_NODISCARD_IS_ACTIVE | 1 if BSLA_NODISCARD is active and 0 otherwise |
BSLA_NODISCARD_CPP17 | insert C++17 [[nodiscard]] if available |
BSLA_NODISCARD_CPP17_IS_ACTIVE | 1 if BSLA_NODISCARD_CPP17 is active, or 0 |
BSLA_NODISCARD
does. C++17 and later compilers also support annotating types, BSLA_NODISCARD_CPP17
is defined when such annotation is supported. BSLA_NODISCARD
This annotation causes a warning to be emitted if the caller of a so-annotated function does not use its return value. This is useful for functions where not checking the result is either a security problem or always a bug, such as with the realloc
function. The annotation cannot be used portably on constructors if C++03 support is required because the GNU compiler reuses their C (language) implementation for compatibility and that does not understand that constructors. Attempt to apply BSLA_NODISCARD
to a constructor will result in a warning from gcc: warning: warn_unused_result
attribute ignored [-Wattributes] 4 | BSLA_NODISCARD Type() {} | ^BSLA_NODISCARD_IS_ACTIVE
The macro BSLA_NODISCARD_IS_ACTIVE
is defined to 0 if BSLA_NODISCARD
expands to nothing and 1 otherwise.BSLA_NODISCARD_CPP17
This annotation can be used on both types and functions. Due to differences in compiler parser implementations this macro must be placed after the class
(or struct
) keyword and before the name of the type; otherwise it might not compile. nodiscard
attribute applied to Type::Type()
with void return type [-Wattributes][[ nodiscard ]]
instead of the whole type, so it is easy to avoidBSLA_NODISCARD_CPP17
in effect makes any functionBSLA_NODISCARD_CPP17
. This ability isBSLA_NODISCARD_CPP17_IS_ACTIVE
The macro BSLA_NODISCARD_CPP17_IS_ACTIVE
is defined to 0 if BSLA_NODISCARD_CPP17
expands to nothing and 1 otherwise.newtonsSqrt
, which uses Newton's method for calculating a square root. Since the function has no side effects, it doesn't make sense to call it and ignore its result, so we annotate it with BSLA_NODISCARD
: BSLA_NODISCARD double newtonsSqrt(double x); double newtonsSqrt(double x) // Take the square root of the specified 'x'. The behavior is // undefined unless 'x' is positive. { BSLS_ASSERT(x > 0); double guess = 1.0; for (int ii = 0; ii < 100; ++ii) { guess = (guess + x / guess) / 2; } return guess; }
main
, we call it normally a few times and observe that it works with no compiler warnings generated: printf("Square root of 9.0 = %g\n", newtonsSqrt(9.0)); printf("Square root of 0.01 = %g\n", newtonsSqrt(0.01)); printf("Square root of 0.917 * 0.917 = %g\n", newtonsSqrt(0.917 * 0.917));
newtonsSqrt(36.0);
(void) newtonsSqrt(25.0);
.../bsla_nodiscard.t.cpp:289:22: warning: ignoring return value of 'double newtonsSqrt(double)', declared with attribute warn_unused_result [-Wunused-result] newtonsSqrt(36.0); ^ .../bsla_nodiscard.t.cpp:294:29: warning: ignoring return value of 'double newtonsSqrt(double)', declared with attribute warn_unused_result [-Wunused-result] (void) newtonsSqrt(25.0); ^
DelimiterGuard0
: class DelimGuard0 { private: // DATA const char *d_closingText_p; // Held, not owned public: // CREATORS explicit DelimGuard0(const char *closingText); // Create a delimiter guard that upon its destruction prints the // specified 'closingText' to 'stdout'. The behavior is undefined // unless 'closingText' outlives the created object. ~DelimGuard0(); // Print the closing text to the output file, then destroy this // object. };
void guard0ProperUse() { printf("\n```ruby\n"); DelimGuard0 closeCode("```\n"); // Suppose long and complicated code with early returns writing some // source code between the delimiters. Instead we write something // trivial for brevity: printf("puts 'Hello World'\n"); }
guard0ProperUse(); // prints: [\n]```ruby[\n]puts 'Hello World'[\n]```[\n]
<expression>;
. Expression statements execute an expression for its side effects, then destroy all temporaries created in the expression "at the semicolon". All the printf
function calls below are expression statements, they just don't have any temporaries to destroy. void discardedGuard0() { printf("("); DelimGuard0(")\n"); printf("in-parens"); }
discardedGuard0(); // prints: ()[\n]in-parens
class BSLA_NODISCARD_CPP17 DelimGuardCpp17 {
void discardedGuardCpp17() { printf("["); DelimGuardCpp17("]"); printf("in-brackets"); }
.../bsla_nodiscard.t.cpp:LLL:CC: warning: ignoring temporary created by a constructor declared with 'nodiscard' attribute [-Wunused-value] printf("["); DelimGuardCpp17("]"); ^~~~~~~~~~~~~~~~~~~~ ...\bsla_nodiscard.t.cpp(227,36): warning C4834: discarding return value of function with 'nodiscard' attribute