Sabtu, 19 Juli 2025

Microsoft C++ Union

 #include <queue>


using namespace std;


enum class WeatherDataType

{

    Temperature, Wind

};


struct TempData

{

    int StationId;

    time_t time;

    double current;

    double max;

    double min;

};


struct WindData

{

    int StationId;

    time_t time;

    int speed;

    short direction;

};


struct Input

{

    WeatherDataType type;

    union

    {

        TempData temp;

        WindData wind;

    };

};


// Functions that are specific to data types

void Process_Temp(TempData t) {}

void Process_Wind(WindData w) {}


void Initialize(std::queue<Input>& inputs)

{

    Input first;

    first.type = WeatherDataType::Temperature;

    first.temp = { 101, 1418855664, 91.8, 108.5, 67.2 };

    inputs.push(first);


    Input second;

    second.type = WeatherDataType::Wind;

    second.wind = { 204, 1418859354, 14, 27 };

    inputs.push(second);

}


int main(int argc, char* argv[])

{

    // Container for all the data records

    queue<Input> inputs;

    Initialize(inputs);

    while (!inputs.empty())

    {

        Input const i = inputs.front();

        switch (i.type)

        {

        case WeatherDataType::Temperature:

            Process_Temp(i.temp);

            break;

        case WeatherDataType::Wind:

            Process_Wind(i.wind);

            break;

        default:

            break;

        }

        inputs.pop();


    }

    return 0;

}

================================

// for MyVariant

#include <crtdbg.h>

#include <new>

#include <utility>


// for sample objects and output

#include <string>

#include <vector>

#include <iostream>


using namespace std;


struct A

{

    A() = default;

    A(int i, const string& str) : num(i), name(str) {}


    int num;

    string name;

    //...

};


struct B

{

    B() = default;

    B(int i, const string& str) : num(i), name(str) {}


    int num;

    string name;

    vector<int> vec;

    // ...

};


enum class Kind { None, A, B, Integer };


#pragma warning (push)

#pragma warning(disable:4624)

class MyVariant

{

public:

    MyVariant()

        : kind_(Kind::None)

    {

    }


    MyVariant(Kind kind)

        : kind_(kind)

    {

        switch (kind_)

        {

        case Kind::None:

            break;

        case Kind::A:

            new (&a_) A();

            break;

        case Kind::B:

            new (&b_) B();

            break;

        case Kind::Integer:

            i_ = 0;

            break;

        default:

            _ASSERT(false);

            break;

        }

    }


    ~MyVariant()

    {

        switch (kind_)

        {

        case Kind::None:

            break;

        case Kind::A:

            a_.~A();

            break;

        case Kind::B:

            b_.~B();

            break;

        case Kind::Integer:

            break;

        default:

            _ASSERT(false);

            break;

        }

        kind_ = Kind::None;

    }


    MyVariant(const MyVariant& other)

        : kind_(other.kind_)

    {

        switch (kind_)

        {

        case Kind::None:

            break;

        case Kind::A:

            new (&a_) A(other.a_);

            break;

        case Kind::B:

            new (&b_) B(other.b_);

            break;

        case Kind::Integer:

            i_ = other.i_;

            break;

        default:

            _ASSERT(false);

            break;

        }

    }


    MyVariant(MyVariant&& other)

        : kind_(other.kind_)

    {

        switch (kind_)

        {

        case Kind::None:

            break;

        case Kind::A:

            new (&a_) A(move(other.a_));

            break;

        case Kind::B:

            new (&b_) B(move(other.b_));

            break;

        case Kind::Integer:

            i_ = other.i_;

            break;

        default:

            _ASSERT(false);

            break;

        }

        other.kind_ = Kind::None;

    }


    MyVariant& operator=(const MyVariant& other)

    {

        if (&other != this)

        {

            switch (other.kind_)

            {

            case Kind::None:

                this->~MyVariant();

                break;

            case Kind::A:

                *this = other.a_;

                break;

            case Kind::B:

                *this = other.b_;

                break;

            case Kind::Integer:

                *this = other.i_;

                break;

            default:

                _ASSERT(false);

                break;

            }

        }

        return *this;

    }


    MyVariant& operator=(MyVariant&& other)

    {

        _ASSERT(this != &other);

        switch (other.kind_)

        {

        case Kind::None:

            this->~MyVariant();

            break;

        case Kind::A:

            *this = move(other.a_);

            break;

        case Kind::B:

            *this = move(other.b_);

            break;

        case Kind::Integer:

            *this = other.i_;

            break;

        default:

            _ASSERT(false);

            break;

        }

        other.kind_ = Kind::None;

        return *this;

    }


    MyVariant(const A& a)

        : kind_(Kind::A), a_(a)

    {

    }


    MyVariant(A&& a)

        : kind_(Kind::A), a_(move(a))

    {

    }


    MyVariant& operator=(const A& a)

    {

        if (kind_ != Kind::A)

        {

            this->~MyVariant();

            new (this) MyVariant(a);

        }

        else

        {

            a_ = a;

        }

        return *this;

    }


    MyVariant& operator=(A&& a)

    {

        if (kind_ != Kind::A)

        {

            this->~MyVariant();

            new (this) MyVariant(move(a));

        }

        else

        {

            a_ = move(a);

        }

        return *this;

    }


    MyVariant(const B& b)

        : kind_(Kind::B), b_(b)

    {

    }


    MyVariant(B&& b)

        : kind_(Kind::B), b_(move(b))

    {

    }


    MyVariant& operator=(const B& b)

    {

        if (kind_ != Kind::B)

        {

            this->~MyVariant();

            new (this) MyVariant(b);

        }

        else

        {

            b_ = b;

        }

        return *this;

    }


    MyVariant& operator=(B&& b)

    {

        if (kind_ != Kind::B)

        {

            this->~MyVariant();

            new (this) MyVariant(move(b));

        }

        else

        {

            b_ = move(b);

        }

        return *this;

    }


    MyVariant(int i)

        : kind_(Kind::Integer), i_(i)

    {

    }


    MyVariant& operator=(int i)

    {

        if (kind_ != Kind::Integer)

        {

            this->~MyVariant();

            new (this) MyVariant(i);

        }

        else

        {

            i_ = i;

        }

        return *this;

    }


    Kind GetKind() const

    {

        return kind_;

    }


    A& GetA()

    {

        _ASSERT(kind_ == Kind::A);

        return a_;

    }


    const A& GetA() const

    {

        _ASSERT(kind_ == Kind::A);

        return a_;

    }


    B& GetB()

    {

        _ASSERT(kind_ == Kind::B);

        return b_;

    }


    const B& GetB() const

    {

        _ASSERT(kind_ == Kind::B);

        return b_;

    }


    int& GetInteger()

    {

        _ASSERT(kind_ == Kind::Integer);

        return i_;

    }


    const int& GetInteger() const

    {

        _ASSERT(kind_ == Kind::Integer);

        return i_;

    }


private:

    Kind kind_;

    union

    {

        A a_;

        B b_;

        int i_;

    };

};

#pragma warning (pop)


int main()

{

    A a(1, "Hello from A");

    B b(2, "Hello from B");


    MyVariant mv_1 = a;


    cout << "mv_1 = a: " << mv_1.GetA().name << endl;

    mv_1 = b;

    cout << "mv_1 = b: " << mv_1.GetB().name << endl;

    mv_1 = A(3, "hello again from A");

    cout << R"aaa(mv_1 = A(3, "hello again from A"): )aaa" << mv_1.GetA().name << endl;

    mv_1 = 42;

    cout << "mv_1 = 42: " << mv_1.GetInteger() << endl;


    b.vec = { 10,20,30,40,50 };


    mv_1 = move(b);

    cout << "After move, mv_1 = b: vec.size = " << mv_1.GetB().vec.size() << endl;


    cout << endl << "Press a letter" << endl;

    char c;

    cin >> c;

}

============

Tidak ada komentar: