CodeNebula
C++11coreintermediate

Inline Namespaces (C++11 Addition)

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

Explanation

Automatically includes namespace contents in parent scope for versioning.

Real-World Scenario

Version library functions without explicit scoping.

Quick Snippet

snippet.cpp
inline namespace V1 { void func() {} }

Full Example

inline_namespaces.cpp
// CodeNebula - C++11 Example: Inline Namespaces
// Compile: g++ -std=c++11 -Wall -Wextra -o example inline_namespaces.cpp
//
// This example demonstrates:
// - inline namespace for API versioning
// - Members of inline namespaces are accessible from the enclosing namespace
// - Switching default version by changing which namespace is inline
// - Library versioning pattern used in real-world code (e.g., libc++)

#include <iostream>
#include <string>

// ============================================================
// 1. Basic inline namespace
// ============================================================
namespace Graphics {
    inline namespace v2 {
        void draw(const std::string& shape) {
            std::cout << "  [v2] Drawing " << shape << " with anti-aliasing" << std::endl;
        }

        struct Color {
            float r, g, b, a;  // v2 added alpha channel
            void print() const {
                std::cout << "  [v2] Color(" << r << ", " << g << ", "
                          << b << ", " << a << ")" << std::endl;
            }
        };
    }

    namespace v1 {
        void draw(const std::string& shape) {
            std::cout << "  [v1] Drawing " << shape << " (basic)" << std::endl;
        }

        struct Color {
            float r, g, b;  // v1 had no alpha
            void print() const {
                std::cout << "  [v1] Color(" << r << ", " << g << ", "
                          << b << ")" << std::endl;
            }
        };
    }
}

// ============================================================
// 2. Library versioning pattern
// ============================================================
namespace MyLib {
    namespace v1 {
        int compute(int x) { return x * 2; }
        std::string format(int x) {
            return "Result: " + std::to_string(x);
        }
    }

    inline namespace v2 {
        int compute(int x) { return x * x; }  // Changed behavior
        std::string format(int x) {
            return "[v2] Result = " + std::to_string(x);
        }
    }

    namespace v3_experimental {
        int compute(int x) { return x * x * x; }
        std::string format(int x) {
            return "[v3-exp] " + std::to_string(x);
        }
    }
}

// ============================================================
// 3. Template specialization across versions
// ============================================================
namespace Serializer {
    inline namespace v2 {
        template <typename T>
        std::string serialize(const T& val) {
            return "{\"value\": " + std::to_string(val) + "}";
        }
    }

    namespace v1 {
        template <typename T>
        std::string serialize(const T& val) {
            return std::to_string(val);
        }
    }
}

int main() {
    std::cout << "=== Inline Namespaces ===" << std::endl;

    // Using default (inline) version
    std::cout << "\n--- Default (inline v2) ---" << std::endl;
    Graphics::draw("Circle");         // Calls v2::draw
    Graphics::Color c1{1.0f, 0.0f, 0.0f, 0.5f};
    c1.print();

    // Explicitly using older version
    std::cout << "\n--- Explicit v1 ---" << std::endl;
    Graphics::v1::draw("Circle");     // Calls v1::draw
    Graphics::v1::Color c2{1.0f, 0.0f, 0.0f};
    c2.print();

    // Library versioning
    std::cout << "\n--- Library versioning ---" << std::endl;
    std::cout << "  MyLib::compute(5) = " << MyLib::compute(5)
              << " (v2: x*x)" << std::endl;
    std::cout << "  MyLib::v1::compute(5) = " << MyLib::v1::compute(5)
              << " (v1: x*2)" << std::endl;
    std::cout << "  MyLib::v3_experimental::compute(5) = "
              << MyLib::v3_experimental::compute(5)
              << " (v3: x*x*x)" << std::endl;

    std::cout << "  " << MyLib::format(25) << std::endl;
    std::cout << "  " << MyLib::v1::format(25) << std::endl;

    // Serializer versioning
    std::cout << "\n--- Serializer versioning ---" << std::endl;
    std::cout << "  Default: " << Serializer::serialize(42) << std::endl;
    std::cout << "  v1:      " << Serializer::v1::serialize(42) << std::endl;

    std::cout << "\nKey: 'inline namespace' makes its members the default" << std::endl;

    return 0;
}

// Expected output:
// === Inline Namespaces ===
//
// --- Default (inline v2) ---
//   [v2] Drawing Circle with anti-aliasing
//   [v2] Color(1, 0, 0, 0.5)
//
// --- Explicit v1 ---
//   [v1] Drawing Circle (basic)
//   [v1] Color(1, 0, 0)
//
// --- Library versioning ---
//   MyLib::compute(5) = 25 (v2: x*x)
//   MyLib::v1::compute(5) = 10 (v1: x*2)
//   MyLib::v3_experimental::compute(5) = 125 (v3: x*x*x)
//   [v2] Result = 25
//   Result: 25
//
// --- Serializer versioning ---
//   Default: {"value": 42}
//   v1:      42
//
// Key: 'inline namespace' makes its members the default
Run command
g++ -std=c++11 -Wall -Wextra -o example inline_namespaces.cpp