template <typename ...T>
class BaseEvent
{
BaseEvent(const unsigned int index, const uint8_t id, const std::variant<T...> data) : m_index(index), m_id(id), m_data(m_data){};
virtual ~BaseEvent();
template <typename V>
const V get()
{
static_assert(constexpr std::is_same_v<V, T...>);
return std::get<V>(m_data);
};
protected:
unsigned int m_index;
uint8_t m_id;
std::variant<T...> m_data;
// pseudocode:
// enable_if(sizeof(T...) > 1)
// then: std::variant<T...> m_data
// else: T m_data
};
However later in the code,
template <class T>
class StringEvent : public BaseEvent<T>
{
virtual ~StringEvent();
const T string() { return get<T>(); };
};
Pasing only a single type to BaseEvent
will not be able to create variant
as it is useless in that case anyways. How can I use enable_if
to create m_data
of type T
when T...
is a single type only?
CodePudding user response:
I have done exactly what you want to do, so I know what you need. To handle both single message and multiple message types, use std::variant<std::monostate, T...>
. In addition, your use of is_same_v<>
is incorrect. You can only use 1 type, not multiple types there.
So you need a code like this:
template <typename ...T>
class BaseEvent
{
BaseEvent(const unsigned int index, const uint8_t id, const std::variant<T...> data) : m_index(index), m_id(id), m_data(m_data){};
// ^-- There is a small bug here in creating variant(different types). you need to solve, and use in-place for variant.
virtual ~BaseEvent();
template <typename V>
const V get()
{
static_assert(is_valid_type<V>() || std::is_same_v<V, std::monostate>);
return std::get<V>(m_data);
};
protected:
unsigned int m_index;
uint8_t m_id;
std::variant<std::monostate, T...> m_data;
private:
template<typename U>
constexpr static bool is_valid_type() {
return (std::is_same_v<U, T> || ...);
}
};
My main code is much more complex and I just extracted small part for this, so use it with care.