Back to TILs

C++ attributes

Date: 2022-12-18Last modified: 2024-11-02

Table of contents

Brief

Attribute [[nodiscard]]

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;
      |   ^~~~~~~~

References