Megidd
Megidd

Reputation: 7938

Use of generic-type for a member of struct

I have a struct:

struct MyStruct {

    const unsigned short *ptr = nullptr;

    /* above pointer might also be:
    const unsigned int   *ptr = nullptr; 
    */

    // ...
};

I use the struct as a member of a class:

class MyClass
{
    // ...

private:
    MyStruct m_struct;
}

Inside member functions of MyClass, I want to be able to have a switch like this:

void MyClass::myFunc()
{
    // ...

    switch(myDataType) {

    case USHORT:
        m_struct.ptr = reinterpret_cast<const unsigned short *>(myDataPtr);
        break;

    case UINT:
        m_struct.ptr = reinterpret_cast<const unsigned int   *>(myDataPtr);
        break;

    default:
        break;

    }
}

Currently, the above switch is not possible due to incompatible types.

I cannot figure out how I should define my struct with a proper template, so that I would be able to do the above switch on class member function.

Upvotes: 2

Views: 142

Answers (3)

Jarod42
Jarod42

Reputation: 217085

std::variant (c++17, else use boost one) might help you:

struct MyStruct {

    std::variant<const unsigned short*, const unsigned int*> ptr{std::in_place_index_t<0>, nullptr}; 

    // ...
};

and then

void MyClass::myFunc()
{
    // ...

    switch(myDataType) {
    case USHORT:
        m_struct.ptr = reinterpret_cast<const unsigned short *>(myDataPtr);
        break;

    case UINT:
        m_struct.ptr = reinterpret_cast<const unsigned int *>(myDataPtr);
        break;

    default:
        break;
    }

    // ...
}

or even simply m_struct.ptr = myDataPtr; if myDataPtr is a std::variant too.

std::visit might also help instead of switch.

Upvotes: 1

Megidd
Megidd

Reputation: 7938

Althouth @songyuanyao answer is more elegant, I cannot use it since I don't know type T at compile time. Therefore I'm currently using the following workaround. I'm not sure if it is the best:

struct MyStruct {

    const unsigned short *ptr_ushort = nullptr;

    // consider the other type:
    const unsigned int   *ptr_uint   = nullptr; 

    // To know what type we have:
    TypeEnum ptr_type;

    // ...
};

Then, I implemented my switch like this:

void MyClass::myFunc()
{
    // ...

    switch(myDataType) {

    case USHORT:
        m_struct.ptr_ushort = reinterpret_cast<const unsigned short *>(myDataPtr);
        m_struct.ptr_type   = TypeEnum::USHORT;
        break;

    case UINT:
        m_struct.ptr_uint   = reinterpret_cast<const unsigned int   *>(myDataPtr);
        m_struct.ptr_type   = TypeEnum::UINT;
        break;

    default:
        break;

    }

    // ...
}

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172884

You can make both of them class template. Then no need to use switch. e.g.

template <typename T>
struct MyStruct {

    const T *ptr = nullptr;

    // ...
};

template <typename T>
class MyClass
{
    // ...

private:
    MyStruct<T> m_struct;
};

template <typename T>
void MyClass<T>::myFunc()
{
    // ...

    m_struct.ptr = reinterpret_cast<const T *>(myData);
}

Upvotes: 4

Related Questions