C++17coreadvanced
[[nodiscard]] Attribute
C++17 · Practical Modern · Compiler flag: -std=c++17
Explanation
Warns the caller if a function's return value is discarded. This catches a common class of bugs where important results (error codes, allocated resources, computed values) are silently ignored.
Real-World Scenario
Prevent callers from ignoring the error code returned by a database connection function.
Quick Snippet
snippet.cpp
[[nodiscard]] bool connect(const std::string& host) {
// returns false on failure
return true;
}
// connect("db.example.com"); // WARNING: discarding return value
bool ok = connect("db.example.com"); // Correct usageFull Example
nodiscard.cpp
// CodeNebula - C++17 Example: [[nodiscard]] Attribute
// Compile: g++ -std=c++17 -Wall -Wextra -o example nodiscard.cpp
// Demonstrates [[nodiscard]], which warns when a function's return value is
// discarded. Useful for error codes, factory functions, and any return value
// that should never be silently ignored.
#include <iostream>
#include <string>
#include <vector>
// ------------------------------------------------------------------
// 1. [[nodiscard]] on a free function returning an error code
// ------------------------------------------------------------------
enum class ErrorCode { Ok, NotFound, PermissionDenied };
[[nodiscard]] ErrorCode open_file(const std::string& name) {
if (name.empty()) return ErrorCode::NotFound;
// Simulate opening a file
return ErrorCode::Ok;
}
// ------------------------------------------------------------------
// 2. [[nodiscard]] on a factory function
// ------------------------------------------------------------------
[[nodiscard]] std::vector<int> generate_sequence(int n) {
std::vector<int> seq;
for (int i = 1; i <= n; ++i) {
seq.push_back(i * i);
}
return seq;
}
// ------------------------------------------------------------------
// 3. [[nodiscard]] on a class (all functions returning it warn)
// ------------------------------------------------------------------
struct [[nodiscard]] Result {
bool success;
std::string message;
};
Result process(int value) {
if (value < 0) return {false, "negative input"};
return {true, "processed " + std::to_string(value)};
}
// ------------------------------------------------------------------
// 4. [[nodiscard]] on a member function
// ------------------------------------------------------------------
class Calculator {
double total_ = 0.0;
public:
void add(double v) { total_ += v; }
[[nodiscard]] double get_total() const { return total_; }
[[nodiscard]] bool is_positive() const { return total_ > 0; }
};
int main()
{
// 1. Error code -- using the return value (no warning)
std::cout << "=== [[nodiscard]] error code ===" << std::endl;
ErrorCode ec = open_file("data.txt");
std::cout << " open_file(\"data.txt\"): "
<< (ec == ErrorCode::Ok ? "Ok" : "Error") << std::endl;
ec = open_file("");
std::cout << " open_file(\"\"): "
<< (ec == ErrorCode::NotFound ? "NotFound" : "Other") << std::endl;
// NOTE: open_file("test.txt"); without capturing would produce a warning:
// warning: ignoring return value of function declared with 'nodiscard'
// 2. Factory function
std::cout << "\n=== [[nodiscard]] factory ===" << std::endl;
auto seq = generate_sequence(5);
std::cout << " squares: ";
for (int v : seq) std::cout << v << " ";
std::cout << std::endl;
// 3. [[nodiscard]] struct
std::cout << "\n=== [[nodiscard]] struct ===" << std::endl;
Result r = process(42);
std::cout << " process(42): " << r.message
<< " (success=" << std::boolalpha << r.success << ")" << std::endl;
r = process(-1);
std::cout << " process(-1): " << r.message
<< " (success=" << r.success << ")" << std::endl;
// 4. Member functions
std::cout << "\n=== [[nodiscard]] member functions ===" << std::endl;
Calculator calc;
calc.add(10.5);
calc.add(20.3);
double total = calc.get_total();
std::cout << " total: " << total << std::endl;
std::cout << " positive: " << calc.is_positive() << std::endl;
return 0;
}
/*
Expected output:
=== [[nodiscard]] error code ===
open_file("data.txt"): Ok
open_file(""): NotFound
=== [[nodiscard]] factory ===
squares: 1 4 9 16 25
=== [[nodiscard]] struct ===
process(42): processed 42 (success=true)
process(-1): negative input (success=false)
=== [[nodiscard]] member functions ===
total: 30.8
positive: true
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example nodiscard.cpp