cpp

examples

examples.cpp⚙️
/**
 * Preprocessor Directives & Namespaces - Examples
 * Comprehensive demonstration of all preprocessor features and namespaces
 */

#include <iostream>
#include <string>
#include <chrono>

using std::cout;
using std::endl;
using std::string;

// ============================================================================
// SECTION 1: Basic Macros
// ============================================================================

// Object-like macros (constants)
#define MACRO_PI 3.14159265359  // ⚠️ LEARNING NOTE: Renamed from PI!
// PROBLEM: Later in this file, we also define 'const double PI'
// Macros are text replacement - the compiler sees:
//     const double 3.14159265359 = 3.14159265359;  // ERROR!
// 
// LESSON: Avoid naming macros the same as variables!
// Better practice: Use ALL_CAPS with prefix for macros, or use constexpr instead
#define MAX_BUFFER_SIZE 1024
#define APP_VERSION "1.0.0"
#define ENABLE_LOGGING

// Function-like macros
#define SQUARE(x) ((x) * (x))
#define CUBE(x) ((x) * (x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))

// Stringification
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

// Token pasting
#define MAKE_FUNCTION(name) void name##_function() { cout << #name " function called" << endl; }
#define DECLARE_VAR(type, name) type var_##name

void demonstrateBasicMacros() {
    cout << "\n=== BASIC MACROS ===" << endl;
    
    // Object-like macros
    // ⚠️ Note: We use MACRO_PI here (not PI) to avoid conflict with Math::PI later
    cout << "MACRO_PI = " << MACRO_PI << endl;
    cout << "MAX_BUFFER_SIZE = " << MAX_BUFFER_SIZE << endl;
    cout << "APP_VERSION = " << APP_VERSION << endl;
    
    // Function-like macros
    cout << "\nFunction-like macros:" << endl;
    cout << "SQUARE(5) = " << SQUARE(5) << endl;
    cout << "CUBE(3) = " << CUBE(3) << endl;
    cout << "MAX(10, 20) = " << MAX(10, 20) << endl;
    cout << "MIN(10, 20) = " << MIN(10, 20) << endl;
    cout << "ABS(-15) = " << ABS(-15) << endl;
    
    // Demonstrating why parentheses matter
    cout << "\nWhy parentheses matter in SQUARE:" << endl;
    cout << "SQUARE(2 + 3) = " << SQUARE(2 + 3) << " (correct: 25)" << endl;
    // Without parentheses it would be: 2 + 3 * 2 + 3 = 11
    
    // Stringification
    cout << "\nStringification:" << endl;
    cout << "STRINGIFY(Hello World) = " << STRINGIFY(Hello World) << endl;
    cout << "TOSTRING(12345) = " << TOSTRING(12345) << endl;
    cout << "TOSTRING(MAX_BUFFER_SIZE) = " << TOSTRING(MAX_BUFFER_SIZE) << endl;
    
    // Token pasting
    cout << "\nToken pasting - declaring variables:" << endl;
    DECLARE_VAR(int, count) = 42;
    DECLARE_VAR(double, value) = 3.14;
    cout << "var_count = " << var_count << endl;
    cout << "var_value = " << var_value << endl;
}

// Create functions using macro
MAKE_FUNCTION(test)
MAKE_FUNCTION(demo)

void demonstrateGeneratedFunctions() {
    cout << "\n=== MACRO-GENERATED FUNCTIONS ===" << endl;
    test_function();
    demo_function();
}

// ============================================================================
// SECTION 2: Predefined Macros
// ============================================================================

void demonstratePredefinedMacros() {
    cout << "\n=== PREDEFINED MACROS ===" << endl;
    
    cout << "File: " << __FILE__ << endl;
    cout << "Line: " << __LINE__ << endl;
    cout << "Date: " << __DATE__ << endl;
    cout << "Time: " << __TIME__ << endl;
    cout << "Function: " << __func__ << endl;
    
    // C++ standard version
    cout << "\nC++ Standard Version: ";
#if __cplusplus >= 202002L
    cout << "C++20 or later";
#elif __cplusplus >= 201703L
    cout << "C++17";
#elif __cplusplus >= 201402L
    cout << "C++14";
#elif __cplusplus >= 201103L
    cout << "C++11";
#else
    cout << "Pre-C++11";
#endif
    cout << " (__cplusplus = " << __cplusplus << ")" << endl;
}

// ============================================================================
// SECTION 3: Conditional Compilation
// ============================================================================

// Define debug level
#define DEBUG_LEVEL 2

// Conditional logging based on debug level
#if DEBUG_LEVEL == 0
    #define LOG(msg)
    #define LOG_DEBUG(msg)
    #define LOG_VERBOSE(msg)
#elif DEBUG_LEVEL == 1
    #define LOG(msg) cout << "[LOG] " << msg << endl
    #define LOG_DEBUG(msg)
    #define LOG_VERBOSE(msg)
#elif DEBUG_LEVEL >= 2
    #define LOG(msg) cout << "[LOG] " << msg << endl
    #define LOG_DEBUG(msg) cout << "[DEBUG] " << __func__ << ":" << __LINE__ << " - " << msg << endl
    #define LOG_VERBOSE(msg) cout << "[VERBOSE] " << __FILE__ << ":" << __LINE__ << " - " << msg << endl
#endif

void demonstrateConditionalCompilation() {
    cout << "\n=== CONDITIONAL COMPILATION ===" << endl;
    cout << "DEBUG_LEVEL = " << DEBUG_LEVEL << endl;
    
    LOG("This is a log message");
    LOG_DEBUG("This is a debug message");
    LOG_VERBOSE("This is a verbose message");
    
    // ifdef/ifndef
#ifdef ENABLE_LOGGING
    cout << "\nLogging is ENABLED" << endl;
#else
    cout << "\nLogging is DISABLED" << endl;
#endif

#ifndef PRODUCTION
    cout << "Not in production mode" << endl;
#endif
}

// ============================================================================
// SECTION 4: Platform Detection
// ============================================================================

void demonstratePlatformDetection() {
    cout << "\n=== PLATFORM DETECTION ===" << endl;
    
#if defined(_WIN32) || defined(_WIN64)
    cout << "Platform: Windows" << endl;
    #ifdef _WIN64
        cout << "Architecture: 64-bit" << endl;
    #else
        cout << "Architecture: 32-bit" << endl;
    #endif
#elif defined(__linux__)
    cout << "Platform: Linux" << endl;
#elif defined(__APPLE__) && defined(__MACH__)
    cout << "Platform: macOS" << endl;
#elif defined(__FreeBSD__)
    cout << "Platform: FreeBSD" << endl;
#else
    cout << "Platform: Unknown" << endl;
#endif

    // Compiler detection
    cout << "\nCompiler: ";
#if defined(__clang__)
    cout << "Clang " << __clang_major__ << "." << __clang_minor__ << endl;
#elif defined(__GNUC__)
    cout << "GCC " << __GNUC__ << "." << __GNUC_MINOR__ << endl;
#elif defined(_MSC_VER)
    cout << "MSVC " << _MSC_VER << endl;
#else
    cout << "Unknown" << endl;
#endif
}

// ============================================================================
// SECTION 5: Namespaces
// ============================================================================

namespace Math {
    const double PI = 3.14159265359;
    const double E = 2.71828182845;
    
    double square(double x) { return x * x; }
    double cube(double x) { return x * x * x; }
    double circleArea(double radius) { return PI * square(radius); }
    double sphereVolume(double radius) { return (4.0/3.0) * PI * cube(radius); }
}

namespace Physics {
    const double G = 9.81;  // Gravity (m/s²)
    const double C = 299792458;  // Speed of light (m/s)
    
    double velocity(double distance, double time) {
        return distance / time;
    }
    
    double kineticEnergy(double mass, double velocity) {
        return 0.5 * mass * velocity * velocity;
    }
}

namespace Utilities {
    namespace String {
        string toUpper(string s) {
            for (char& c : s) c = toupper(c);
            return s;
        }
        
        string toLower(string s) {
            for (char& c : s) c = tolower(c);
            return s;
        }
    }
    
    namespace Math {  // Different from global Math namespace
        int factorial(int n) {
            return n <= 1 ? 1 : n * factorial(n - 1);
        }
    }
}

void demonstrateNamespaces() {
    cout << "\n=== NAMESPACES ===" << endl;
    
    // Fully qualified names
    cout << "Math::PI = " << Math::PI << endl;
    cout << "Math::circleArea(5) = " << Math::circleArea(5) << endl;
    cout << "Math::sphereVolume(3) = " << Math::sphereVolume(3) << endl;
    
    cout << "\nPhysics::G = " << Physics::G << endl;
    cout << "Physics::velocity(100, 10) = " << Physics::velocity(100, 10) << endl;
    cout << "Physics::kineticEnergy(10, 5) = " << Physics::kineticEnergy(10, 5) << endl;
    
    // Nested namespaces
    cout << "\nUtilities::String::toUpper(\"hello\") = " 
         << Utilities::String::toUpper("hello") << endl;
    cout << "Utilities::Math::factorial(5) = " 
         << Utilities::Math::factorial(5) << endl;
}

// C++17 nested namespace syntax
namespace Company::Product::Feature {
    void doSomething() {
        cout << "Feature activated!" << endl;
    }
}

// Namespace alias
namespace CPF = Company::Product::Feature;

void demonstrateNestedNamespaces() {
    cout << "\n=== NESTED NAMESPACES (C++17) ===" << endl;
    
    Company::Product::Feature::doSomething();
    
    // Using alias
    cout << "Using namespace alias:" << endl;
    CPF::doSomething();
}

// ============================================================================
// SECTION 6: using Declarations and Directives
// ============================================================================

namespace Graphics {
    struct Point { int x, y; };
    struct Color { int r, g, b; };
    
    void drawPoint(Point p) {
        cout << "Drawing point at (" << p.x << ", " << p.y << ")" << endl;
    }
    
    void setColor(Color c) {
        cout << "Setting color to RGB(" << c.r << ", " << c.g << ", " << c.b << ")" << endl;
    }
}

void demonstrateUsingDeclarations() {
    cout << "\n=== using DECLARATIONS ===" << endl;
    
    // using declaration - bring specific names into scope
    using Graphics::Point;
    using Graphics::drawPoint;
    
    Point p{10, 20};
    drawPoint(p);
    
    // Still need full qualification for other members
    Graphics::Color color{255, 128, 0};
    Graphics::setColor(color);
}

void demonstrateUsingDirective() {
    cout << "\n=== using DIRECTIVE (in function scope) ===" << endl;
    
    // using directive - bring all names into scope
    // Safe here because it's in function scope
    using namespace Graphics;
    
    Point p1{5, 10};
    Point p2{15, 25};
    Color red{255, 0, 0};
    
    drawPoint(p1);
    drawPoint(p2);
    setColor(red);
}

// ============================================================================
// SECTION 7: Anonymous Namespace
// ============================================================================

// Anonymous namespace - internal linkage
namespace {
    int internalCounter = 0;
    
    void internalHelper() {
        cout << "Internal helper called, counter = " << ++internalCounter << endl;
    }
}

void demonstrateAnonymousNamespace() {
    cout << "\n=== ANONYMOUS NAMESPACE ===" << endl;
    cout << "These functions/variables have internal linkage (file-private)" << endl;
    
    internalHelper();
    internalHelper();
    internalHelper();
}

// ============================================================================
// SECTION 8: Inline Namespace (Library Versioning)
// ============================================================================

namespace MyLibrary {
    inline namespace v2 {  // Current default version
        struct Data {
            int value;
            string name;
            
            void print() const {
                cout << "v2::Data{value=" << value << ", name=\"" << name << "\"}" << endl;
            }
        };
    }
    
    namespace v1 {  // Legacy version
        struct Data {
            int value;
            
            void print() const {
                cout << "v1::Data{value=" << value << "}" << endl;
            }
        };
    }
}

void demonstrateInlineNamespace() {
    cout << "\n=== INLINE NAMESPACE (Versioning) ===" << endl;
    
    // Uses v2 by default (inline namespace)
    MyLibrary::Data current{42, "Modern"};
    current.print();
    
    // Explicitly use v1
    MyLibrary::v1::Data legacy{100};
    legacy.print();
    
    // Explicitly use v2
    MyLibrary::v2::Data explicit_v2{200, "Explicit"};
    explicit_v2.print();
}

// ============================================================================
// SECTION 9: Practical Debug Macro System
// ============================================================================

// Undefine previous logging macros
#undef LOG
#undef LOG_DEBUG
#undef LOG_VERBOSE

// Production-ready debug macro system
#define DEBUG_ENABLED

#ifdef DEBUG_ENABLED
    #define ASSERT(condition, message) \
        do { \
            if (!(condition)) { \
                std::cerr << "ASSERTION FAILED: " << message << "\n" \
                          << "  Condition: " << #condition << "\n" \
                          << "  File: " << __FILE__ << "\n" \
                          << "  Line: " << __LINE__ << "\n" \
                          << "  Function: " << __func__ << std::endl; \
            } \
        } while(0)
    
    #define DEBUG_LOG(msg) \
        cout << "[DEBUG] " << __func__ << ": " << msg << endl
    
    #define TRACE_ENTER() \
        cout << "[TRACE] Entering: " << __func__ << endl
    
    #define TRACE_EXIT() \
        cout << "[TRACE] Exiting: " << __func__ << endl
#else
    #define ASSERT(condition, message) ((void)0)
    #define DEBUG_LOG(msg) ((void)0)
    #define TRACE_ENTER() ((void)0)
    #define TRACE_EXIT() ((void)0)
#endif

void demonstratePracticalMacros() {
    TRACE_ENTER();
    cout << "\n=== PRACTICAL DEBUG MACRO SYSTEM ===" << endl;
    
    int value = 42;
    DEBUG_LOG("Value is " << value);
    
    ASSERT(value > 0, "Value should be positive");
    ASSERT(value < 100, "Value should be less than 100");
    
    // This assertion will fail and print debug info
    // ASSERT(value > 100, "This will fail");
    
    TRACE_EXIT();
}

// ============================================================================
// SECTION 10: Compile-Time Profiling Macros
// ============================================================================

#define ENABLE_PROFILING

#ifdef ENABLE_PROFILING
    #define PROFILE_SCOPE(name) \
        auto _profile_start_##name = std::chrono::high_resolution_clock::now(); \
        struct _ProfileScope_##name { \
            const char* _name; \
            decltype(_profile_start_##name) _start; \
            _ProfileScope_##name(const char* n, decltype(_profile_start_##name) s) : _name(n), _start(s) {} \
            ~_ProfileScope_##name() { \
                auto _end = std::chrono::high_resolution_clock::now(); \
                auto _duration = std::chrono::duration<double, std::milli>(_end - _start); \
                cout << "[PROFILE] " << _name << ": " << _duration.count() << " ms" << endl; \
            } \
        } _profile_instance_##name(#name, _profile_start_##name)
#else
    #define PROFILE_SCOPE(name)
#endif

void demonstrateProfilingMacros() {
    cout << "\n=== PROFILING MACROS ===" << endl;
    
    {
        PROFILE_SCOPE(StringOperations);
        string result;
        for (int i = 0; i < 10000; ++i) {
            result += "x";
        }
    }
    
    {
        PROFILE_SCOPE(MathCalculations);
        double sum = 0;
        for (int i = 0; i < 100000; ++i) {
            sum += Math::square(i) + Math::cube(i % 100);
        }
    }
}

// ============================================================================
// MAIN
// ============================================================================

int main() {
    cout << "╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║       PREPROCESSOR DIRECTIVES & NAMESPACES EXAMPLES          ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    // Macro examples
    demonstrateBasicMacros();
    demonstrateGeneratedFunctions();
    demonstratePredefinedMacros();
    demonstrateConditionalCompilation();
    demonstratePlatformDetection();
    
    // Namespace examples
    demonstrateNamespaces();
    demonstrateNestedNamespaces();
    demonstrateUsingDeclarations();
    demonstrateUsingDirective();
    demonstrateAnonymousNamespace();
    demonstrateInlineNamespace();
    
    // Practical examples
    demonstratePracticalMacros();
    demonstrateProfilingMacros();
    
    cout << "\n═══════════════════════════════════════════════════════════════" << endl;
    cout << "All examples completed!" << endl;
    
    return 0;
}
Examples - C++ Tutorial | DeepML