cpp

examples

examples.cpp⚙️
/**
 * Enums, Structs, and Unions - Examples
 * Comprehensive demonstration of custom data types in C++
 */

#include <iostream>
#include <string>
#include <cstring>
#include <variant>
#include <type_traits>
#include <cmath>

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

// ============================================================================
// SECTION 1: Traditional Enums
// ============================================================================

// Traditional enum (C-style)
enum Color {
    RED = 0,
    GREEN = 1,
    BLUE = 2
};

enum Priority {
    LOW = 1,
    MEDIUM = 5,
    HIGH = 10,
    CRITICAL = 100
};

void demonstrateTraditionalEnums() {
    cout << "\n=== TRADITIONAL ENUMS ===" << endl;
    
    Color c = RED;
    Priority p = HIGH;
    
    cout << "Color RED = " << c << endl;
    cout << "Priority HIGH = " << p << endl;
    
    // Implicit conversion to int (problematic!)
    int colorValue = c;
    cout << "Color as int: " << colorValue << endl;
    
    // Can compare different enums (problematic!)
    if (RED == LOW - 1) {
        cout << "RED equals LOW - 1 (both are 0) - This is problematic!" << endl;
    }
    
    // Switch statement
    switch (p) {
        case LOW: cout << "Low priority" << endl; break;
        case MEDIUM: cout << "Medium priority" << endl; break;
        case HIGH: cout << "High priority" << endl; break;
        case CRITICAL: cout << "CRITICAL priority!" << endl; break;
    }
}

// ============================================================================
// SECTION 2: Enum Class (Scoped Enums)
// ============================================================================

// Strongly typed enum class
enum class Direction {
    North,
    South,
    East,
    West
};

enum class TrafficLight {
    Red,
    Yellow,
    Green
};

// With underlying type
enum class ErrorCode : uint16_t {
    None = 0,
    NotFound = 404,
    ServerError = 500,
    Timeout = 408
};

// Small enum for memory efficiency
enum class DayOfWeek : uint8_t {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

// Helper function to convert enum class to underlying type
template<typename E>
constexpr auto toUnderlying(E e) noexcept {
    return static_cast<std::underlying_type_t<E>>(e);
}

void demonstrateEnumClass() {
    cout << "\n=== ENUM CLASS (SCOPED ENUMS) ===" << endl;
    
    Direction dir = Direction::North;
    TrafficLight light = TrafficLight::Red;
    ErrorCode error = ErrorCode::NotFound;
    DayOfWeek day = DayOfWeek::Monday;
    
    // Must use explicit cast to get int value
    cout << "Direction::North = " << static_cast<int>(dir) << endl;
    cout << "TrafficLight::Red = " << static_cast<int>(light) << endl;
    cout << "ErrorCode::NotFound = " << toUnderlying(error) << endl;
    
    // Size comparison
    cout << "\nSize comparison:" << endl;
    cout << "sizeof(Direction) = " << sizeof(Direction) << " bytes" << endl;
    cout << "sizeof(ErrorCode) = " << sizeof(ErrorCode) << " bytes" << endl;
    cout << "sizeof(DayOfWeek) = " << sizeof(DayOfWeek) << " byte" << endl;
    
    // Type-safe comparisons
    // if (dir == light) {}  // Compile error! Different types
    
    if (dir == Direction::North) {
        cout << "\nHeading North!" << endl;
    }
    
    // Switch with enum class
    switch (light) {
        case TrafficLight::Red: cout << "STOP!" << endl; break;
        case TrafficLight::Yellow: cout << "Caution..." << endl; break;
        case TrafficLight::Green: cout << "GO!" << endl; break;
    }
}

// ============================================================================
// SECTION 3: Basic Structs
// ============================================================================

// Simple struct
struct Point2D {
    double x;
    double y;
};

// Struct with default values (C++11)
struct Point3D {
    double x = 0.0;
    double y = 0.0;
    double z = 0.0;
};

// Struct with methods
struct Rectangle {
    double width;
    double height;
    
    // Member functions
    double area() const { return width * height; }
    double perimeter() const { return 2 * (width + height); }
    double diagonal() const { return std::sqrt(width*width + height*height); }
    
    // Mutating function
    void scale(double factor) {
        width *= factor;
        height *= factor;
    }
    
    // Static factory method
    static Rectangle square(double side) {
        return {side, side};
    }
    
    // Print function
    void print() const {
        cout << "Rectangle(" << width << " x " << height 
             << ", area=" << area() << ")" << endl;
    }
};

void demonstrateBasicStructs() {
    cout << "\n=== BASIC STRUCTS ===" << endl;
    
    // Different initialization styles
    Point2D p1;                     // Uninitialized (garbage values!)
    Point2D p2 = {3.0, 4.0};        // Aggregate initialization
    Point2D p3{1.0, 2.0};           // Uniform initialization (C++11)
    Point2D p4 = {};                // Zero initialization
    
    // Point3D has default values
    Point3D p5;                     // All zeros due to defaults
    Point3D p6{1.0, 2.0};           // z defaults to 0.0
    
    cout << "p2: (" << p2.x << ", " << p2.y << ")" << endl;
    cout << "p3: (" << p3.x << ", " << p3.y << ")" << endl;
    cout << "p5: (" << p5.x << ", " << p5.y << ", " << p5.z << ")" << endl;
    cout << "p6: (" << p6.x << ", " << p6.y << ", " << p6.z << ")" << endl;
    
    // Rectangle with methods
    Rectangle rect{10.0, 5.0};
    rect.print();
    cout << "Diagonal: " << rect.diagonal() << endl;
    
    rect.scale(2.0);
    cout << "After scaling by 2: ";
    rect.print();
    
    // Static factory
    Rectangle sq = Rectangle::square(5.0);
    cout << "Square: ";
    sq.print();
}

// ============================================================================
// SECTION 4: Nested Structs
// ============================================================================

struct Address {
    string street;
    string city;
    string state;
    string zipCode;
    string country;
    
    void print() const {
        cout << street << endl;
        cout << city << ", " << state << " " << zipCode << endl;
        cout << country << endl;
    }
};

struct Person {
    string firstName;
    string lastName;
    int age;
    Address address;    // Nested struct
    
    string fullName() const {
        return firstName + " " + lastName;
    }
    
    void print() const {
        cout << "Name: " << fullName() << endl;
        cout << "Age: " << age << endl;
        cout << "Address:" << endl;
        address.print();
    }
};

struct Company {
    string name;
    Address headquarters;
    Person ceo;
    int employeeCount;
    
    void print() const {
        cout << "Company: " << name << endl;
        cout << "Employees: " << employeeCount << endl;
        cout << "CEO: " << ceo.fullName() << endl;
        cout << "Headquarters:" << endl;
        headquarters.print();
    }
};

void demonstrateNestedStructs() {
    cout << "\n=== NESTED STRUCTS ===" << endl;
    
    Person person = {
        "John",
        "Doe",
        35,
        {"123 Main St", "New York", "NY", "10001", "USA"}
    };
    
    person.print();
    
    cout << "\n--- Company Example ---" << endl;
    
    Company company = {
        "TechCorp Inc.",
        {"456 Tech Blvd", "San Francisco", "CA", "94102", "USA"},
        {"Jane", "Smith", 45, {"789 Exec Lane", "San Francisco", "CA", "94103", "USA"}},
        5000
    };
    
    company.print();
}

// ============================================================================
// SECTION 5: Struct Memory Layout
// ============================================================================

// Struct with potential padding
struct Padded {
    char a;     // 1 byte
    // 3 bytes padding (to align int)
    int b;      // 4 bytes
    char c;     // 1 byte
    // 3 bytes padding (to align struct size to 4)
};

// Reorganized to minimize padding
struct Optimized {
    int b;      // 4 bytes
    char a;     // 1 byte
    char c;     // 1 byte
    // 2 bytes padding (to align struct size to 4)
};

// Packed struct (no padding, slower access)
#pragma pack(push, 1)
struct Packed {
    char a;     // 1 byte
    int b;      // 4 bytes
    char c;     // 1 byte
};
#pragma pack(pop)

void demonstrateMemoryLayout() {
    cout << "\n=== STRUCT MEMORY LAYOUT ===" << endl;
    
    cout << "Padded struct layout:" << endl;
    cout << "  sizeof(Padded) = " << sizeof(Padded) << " bytes" << endl;
    cout << "  Members: char(1) + int(4) + char(1) = 6 bytes" << endl;
    cout << "  With padding: 12 bytes" << endl;
    
    cout << "\nOptimized struct layout:" << endl;
    cout << "  sizeof(Optimized) = " << sizeof(Optimized) << " bytes" << endl;
    cout << "  Members: int(4) + char(1) + char(1) = 6 bytes" << endl;
    cout << "  With padding: 8 bytes" << endl;
    
    cout << "\nPacked struct layout:" << endl;
    cout << "  sizeof(Packed) = " << sizeof(Packed) << " bytes" << endl;
    cout << "  Members: char(1) + int(4) + char(1) = 6 bytes" << endl;
    cout << "  No padding (may be slower!)" << endl;
    
    // Show offsets
    cout << "\nPadded member offsets:" << endl;
    cout << "  offsetof(Padded, a) = " << offsetof(Padded, a) << endl;
    cout << "  offsetof(Padded, b) = " << offsetof(Padded, b) << endl;
    cout << "  offsetof(Padded, c) = " << offsetof(Padded, c) << endl;
}

// ============================================================================
// SECTION 6: Basic Unions
// ============================================================================

union IntFloat {
    int i;
    float f;
};

union MultiType {
    int8_t byte;
    int16_t word;
    int32_t dword;
    int64_t qword;
    float single;
    double dbl;
};

void demonstrateBasicUnions() {
    cout << "\n=== BASIC UNIONS ===" << endl;
    
    IntFloat u;
    cout << "sizeof(IntFloat) = " << sizeof(u) << " bytes" << endl;
    
    u.i = 42;
    cout << "After u.i = 42:" << endl;
    cout << "  u.i = " << u.i << endl;
    cout << "  u.f = " << u.f << " (garbage - wrong type!)" << endl;
    
    u.f = 3.14f;
    cout << "\nAfter u.f = 3.14f:" << endl;
    cout << "  u.f = " << u.f << endl;
    cout << "  u.i = " << u.i << " (garbage - wrong type!)" << endl;
    
    // MultiType union
    cout << "\nMultiType union sizes:" << endl;
    cout << "  sizeof(MultiType) = " << sizeof(MultiType) << " bytes" << endl;
    cout << "  (Size of largest member: double = 8 bytes)" << endl;
}

// ============================================================================
// SECTION 7: Tagged Union (Discriminated Union)
// ============================================================================

enum class ValueType { Integer, Float, String };

struct TaggedValue {
    ValueType type;
    union {
        int intValue;
        float floatValue;
        char stringValue[32];  // Fixed-size string buffer
    };
    
    // Factory methods
    static TaggedValue fromInt(int v) {
        TaggedValue tv;
        tv.type = ValueType::Integer;
        tv.intValue = v;
        return tv;
    }
    
    static TaggedValue fromFloat(float v) {
        TaggedValue tv;
        tv.type = ValueType::Float;
        tv.floatValue = v;
        return tv;
    }
    
    static TaggedValue fromString(const char* s) {
        TaggedValue tv;
        tv.type = ValueType::String;
        strncpy(tv.stringValue, s, 31);
        tv.stringValue[31] = '\0';
        return tv;
    }
    
    void print() const {
        switch (type) {
            case ValueType::Integer:
                cout << "Integer: " << intValue << endl;
                break;
            case ValueType::Float:
                cout << "Float: " << floatValue << endl;
                break;
            case ValueType::String:
                cout << "String: " << stringValue << endl;
                break;
        }
    }
};

void demonstrateTaggedUnion() {
    cout << "\n=== TAGGED UNION ===" << endl;
    
    TaggedValue values[] = {
        TaggedValue::fromInt(42),
        TaggedValue::fromFloat(3.14159f),
        TaggedValue::fromString("Hello, World!")
    };
    
    for (const auto& v : values) {
        v.print();
    }
    
    cout << "\nsizeof(TaggedValue) = " << sizeof(TaggedValue) << " bytes" << endl;
}

// ============================================================================
// SECTION 8: std::variant (C++17 Type-Safe Union)
// ============================================================================

void demonstrateStdVariant() {
    cout << "\n=== std::variant (C++17) ===" << endl;
    
    // Type-safe union
    std::variant<int, float, string> value;
    
    value = 42;
    cout << "Stored int: " << std::get<int>(value) << endl;
    cout << "  index() = " << value.index() << endl;
    
    value = 3.14f;
    cout << "\nStored float: " << std::get<float>(value) << endl;
    cout << "  index() = " << value.index() << endl;
    
    value = string("Hello variant!");
    cout << "\nStored string: " << std::get<string>(value) << endl;
    cout << "  index() = " << value.index() << endl;
    
    // Safe access with get_if
    cout << "\nSafe access with get_if:" << endl;
    if (auto* pInt = std::get_if<int>(&value)) {
        cout << "  It's an int: " << *pInt << endl;
    } else if (auto* pFloat = std::get_if<float>(&value)) {
        cout << "  It's a float: " << *pFloat << endl;
    } else if (auto* pStr = std::get_if<string>(&value)) {
        cout << "  It's a string: " << *pStr << endl;
    }
    
    // std::visit for pattern matching
    cout << "\nUsing std::visit:" << endl;
    value = 100;
    std::visit([](auto&& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<T, int>) {
            cout << "  Visiting int: " << arg << endl;
        } else if constexpr (std::is_same_v<T, float>) {
            cout << "  Visiting float: " << arg << endl;
        } else if constexpr (std::is_same_v<T, string>) {
            cout << "  Visiting string: " << arg << endl;
        }
    }, value);
    
    // holds_alternative
    cout << "\nholds_alternative checks:" << endl;
    cout << "  holds int? " << std::holds_alternative<int>(value) << endl;
    cout << "  holds float? " << std::holds_alternative<float>(value) << endl;
    cout << "  holds string? " << std::holds_alternative<string>(value) << endl;
}

// ============================================================================
// SECTION 9: Bit Fields
// ============================================================================

struct StatusFlags {
    unsigned int isActive : 1;     // 1 bit
    unsigned int isEnabled : 1;    // 1 bit  
    unsigned int priority : 3;     // 3 bits (0-7)
    unsigned int errorCode : 4;    // 4 bits (0-15)
    unsigned int reserved : 23;    // 23 bits
};

// Compact color representation
struct Color8 {
    uint32_t red : 8;
    uint32_t green : 8;
    uint32_t blue : 8;
    uint32_t alpha : 8;
};

// IP packet flags
struct IPFlags {
    uint8_t reserved : 1;
    uint8_t dontFragment : 1;
    uint8_t moreFragments : 1;
    uint8_t unused : 5;
};

void demonstrateBitFields() {
    cout << "\n=== BIT FIELDS ===" << endl;
    
    StatusFlags status = {};
    status.isActive = 1;
    status.isEnabled = 1;
    status.priority = 5;
    status.errorCode = 12;
    
    cout << "StatusFlags:" << endl;
    cout << "  isActive = " << status.isActive << endl;
    cout << "  isEnabled = " << status.isEnabled << endl;
    cout << "  priority = " << status.priority << " (max 7)" << endl;
    cout << "  errorCode = " << status.errorCode << " (max 15)" << endl;
    cout << "  sizeof(StatusFlags) = " << sizeof(StatusFlags) << " bytes" << endl;
    
    // Color
    Color8 color = {255, 128, 64, 255};
    cout << "\nColor8 RGBA:" << endl;
    cout << "  R=" << color.red << " G=" << color.green 
         << " B=" << color.blue << " A=" << color.alpha << endl;
    cout << "  sizeof(Color8) = " << sizeof(Color8) << " bytes" << endl;
    
    // IP Flags
    IPFlags ip = {};
    ip.dontFragment = 1;
    cout << "\nIP Flags:" << endl;
    cout << "  dontFragment = " << (int)ip.dontFragment << endl;
    cout << "  sizeof(IPFlags) = " << sizeof(IPFlags) << " byte" << endl;
}

// ============================================================================
// SECTION 10: Practical Examples
// ============================================================================

// Game entity state
enum class EntityState : uint8_t {
    Idle,
    Moving,
    Attacking,
    Dead
};

struct GameEntity {
    uint32_t id;
    float x, y, z;
    float health;
    EntityState state;
    
    struct Stats {
        int strength;
        int agility;
        int intelligence;
    } stats;
    
    bool isAlive() const { return state != EntityState::Dead && health > 0; }
    
    void takeDamage(float damage) {
        health -= damage;
        if (health <= 0) {
            health = 0;
            state = EntityState::Dead;
        }
    }
    
    void print() const {
        cout << "Entity #" << id << endl;
        cout << "  Position: (" << x << ", " << y << ", " << z << ")" << endl;
        cout << "  Health: " << health << endl;
        cout << "  State: " << static_cast<int>(state) << endl;
        cout << "  Stats: STR=" << stats.strength 
             << " AGI=" << stats.agility
             << " INT=" << stats.intelligence << endl;
    }
};

// Configuration with variant
struct AppConfig {
    using ConfigValue = std::variant<int, double, bool, string>;
    
    string name;
    ConfigValue value;
    
    void print() const {
        cout << name << " = ";
        std::visit([](auto&& v) {
            using T = std::decay_t<decltype(v)>;
            if constexpr (std::is_same_v<T, bool>) {
                cout << (v ? "true" : "false");
            } else {
                cout << v;
            }
        }, value);
        cout << endl;
    }
};

void demonstratePracticalExamples() {
    cout << "\n=== PRACTICAL EXAMPLES ===" << endl;
    
    // Game entity
    cout << "Game Entity:" << endl;
    GameEntity player = {
        1,              // id
        100.0f, 50.0f, 0.0f,  // position
        100.0f,         // health
        EntityState::Idle,
        {10, 15, 8}     // stats
    };
    player.print();
    
    player.takeDamage(30);
    cout << "\nAfter taking 30 damage:" << endl;
    cout << "  Health: " << player.health << endl;
    cout << "  Alive: " << (player.isAlive() ? "Yes" : "No") << endl;
    
    // Configuration values
    cout << "\nApp Configuration:" << endl;
    AppConfig configs[] = {
        {"window_width", 1920},
        {"render_scale", 1.5},
        {"fullscreen", true},
        {"player_name", string("Player1")}
    };
    
    for (const auto& config : configs) {
        config.print();
    }
}

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

int main() {
    cout << "╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║         ENUMS, STRUCTS, AND UNIONS EXAMPLES                  ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    demonstrateTraditionalEnums();
    demonstrateEnumClass();
    demonstrateBasicStructs();
    demonstrateNestedStructs();
    demonstrateMemoryLayout();
    demonstrateBasicUnions();
    demonstrateTaggedUnion();
    demonstrateStdVariant();
    demonstrateBitFields();
    demonstratePracticalExamples();
    
    cout << "\n═══════════════════════════════════════════════════════════════" << endl;
    cout << "All examples completed!" << endl;
    
    return 0;
}
Examples - C++ Tutorial | DeepML