CodeNebula
C++11coreintermediate

Attributes (C++11 Addition)

C++11 · Modern Revolution · Compiler flag: -std=c++11

Explanation

Add metadata to code (e.g., `[[noreturn]]`).

Real-World Scenario

Mark a function that never returns in a system.

Quick Snippet

snippet.cpp
[[noreturn]] void exit() {}

Full Example

attributes.cpp
// CodeNebula - C++11 Example: Attributes
// Compile: g++ -std=c++11 -Wall -Wextra -o example attributes.cpp
//
// This example demonstrates:
// - [[noreturn]] attribute for functions that never return
// - [[carries_dependency]] attribute for dependency ordering
// - Standard attribute syntax [[...]] introduced in C++11
// - How attributes provide metadata to the compiler

#include <iostream>
#include <string>
#include <stdexcept>
#include <cstdlib>

// ============================================================
// 1. [[noreturn]] attribute
// ============================================================
// Tells the compiler this function never returns normally.
// This enables optimizations and suppresses warnings about
// missing return statements after calls to this function.

[[noreturn]] void throwError(const std::string& message) {
    throw std::runtime_error(message);
}

[[noreturn]] void fatalExit(const std::string& reason) {
    std::cerr << "FATAL: " << reason << std::endl;
    std::abort();
}

// ============================================================
// 2. Using [[noreturn]] in practice
// ============================================================
enum class ErrorCode { NONE, FILE_NOT_FOUND, PERMISSION_DENIED, UNKNOWN };

[[noreturn]] void handleFatalError(ErrorCode code) {
    switch (code) {
        case ErrorCode::FILE_NOT_FOUND:
            throw std::runtime_error("File not found");
        case ErrorCode::PERMISSION_DENIED:
            throw std::runtime_error("Permission denied");
        default:
            throw std::runtime_error("Unknown error");
    }
    // No return statement needed - compiler knows function never returns
}

int processFile(const std::string& filename) {
    if (filename.empty()) {
        handleFatalError(ErrorCode::FILE_NOT_FOUND);
        // Compiler knows code below this point is unreachable
    }
    return static_cast<int>(filename.length());
}

// ============================================================
// 3. [[carries_dependency]] attribute
// ============================================================
// Used in concurrent programming with memory ordering.
// Tells the compiler that a function carries a dependency
// chain, allowing it to avoid unnecessary memory fence
// instructions. Typically used with std::memory_order_consume.
//
// Note: In practice, most compilers treat memory_order_consume
// as memory_order_acquire, so this attribute is rarely needed.

// Example declaration (the attribute is on the parameter):
int processData([[carries_dependency]] int* data) {
    // The dependency chain from the pointer is preserved
    if (data != nullptr) {
        return *data + 1;
    }
    return 0;
}

// ============================================================
// 4. Attribute syntax overview
// ============================================================
class Calculator {
public:
    // Attributes can appear on declarations
    int add(int a, int b) { return a + b; }
    int subtract(int a, int b) { return a - b; }

    [[noreturn]] void unsupported() {
        throw std::logic_error("Operation not supported");
    }
};

int main() {
    std::cout << "=== C++11 Attributes ===" << std::endl;

    // Test [[noreturn]] with exception handling
    std::cout << "\n--- [[noreturn]] with exceptions ---" << std::endl;

    try {
        throwError("Test error message");
    } catch (const std::runtime_error& e) {
        std::cout << "  Caught: " << e.what() << std::endl;
    }

    try {
        handleFatalError(ErrorCode::FILE_NOT_FOUND);
    } catch (const std::runtime_error& e) {
        std::cout << "  Caught: " << e.what() << std::endl;
    }

    try {
        handleFatalError(ErrorCode::PERMISSION_DENIED);
    } catch (const std::runtime_error& e) {
        std::cout << "  Caught: " << e.what() << std::endl;
    }

    // processFile uses [[noreturn]] internally
    std::cout << "\n--- processFile ---" << std::endl;
    std::cout << "  processFile(\"data.txt\") = "
              << processFile("data.txt") << std::endl;
    try {
        processFile("");
    } catch (const std::runtime_error& e) {
        std::cout << "  processFile(\"\") threw: " << e.what() << std::endl;
    }

    // [[carries_dependency]]
    std::cout << "\n--- [[carries_dependency]] ---" << std::endl;
    int value = 42;
    std::cout << "  processData(&value) = " << processData(&value) << std::endl;
    std::cout << "  processData(nullptr) = " << processData(nullptr) << std::endl;

    // Calculator
    std::cout << "\n--- Calculator ---" << std::endl;
    Calculator calc;
    std::cout << "  add(5, 3) = " << calc.add(5, 3) << std::endl;
    try {
        calc.unsupported();
    } catch (const std::logic_error& e) {
        std::cout << "  unsupported() threw: " << e.what() << std::endl;
    }

    std::cout << "\nC++11 standard attributes: [[noreturn]], [[carries_dependency]]"
              << std::endl;

    return 0;
}

// Expected output:
// === C++11 Attributes ===
//
// --- [[noreturn]] with exceptions ---
//   Caught: Test error message
//   Caught: File not found
//   Caught: Permission denied
//
// --- processFile ---
//   processFile("data.txt") = 8
//   processFile("") threw: File not found
//
// --- [[carries_dependency]] ---
//   processData(&value) = 43
//   processData(nullptr) = 0
//
// --- Calculator ---
//   add(5, 3) = 8
//   unsupported() threw: Operation not supported
//
// C++11 standard attributes: [[noreturn]], [[carries_dependency]]
Run command
g++ -std=c++11 -Wall -Wextra -o example attributes.cpp