I have two unrelated types: Object
and Unrelated
implementing the same basic interface Interface
(for storing in the same container).
I have an enum class that basically maps these types to enums
enum class TypeEnum {
TYPE_OBJECT,
TYPE_UNRELATED,
};
I have a reading method, that basically down-casts from the Interface to an implementation class
template<typename DATA>
const DATA& Read(const Container<Interface>& container, TypeEnum type);
Is it possible to automate the code, such that (this is a pseudo code)
switch(type_enum) {
case TYPE_OBJECT:
return Read<Object>(container, type_enum);
case TYPE_UNRELATED:
return Read<Unrelated>(container, type_enum);
}
can be made into a one liner?
NB. I have a bunch of enum values around 50 and a number of places i want to use this idiom.
In my want-to-have way, I would prefer something aka
template<TypeName>
struct TypePicker;
template<>
struct TypePicker<TYPE_OBJECT> {
typedef Object underlying_type;
};
template<>
struct TypePicker<TYPE_UNRELATED> {
typedef Unrelated underlying_type;
};
and then
return Read<TypePicker<type_enum>::underlying_type>(container, type_enum);
However, type_enum is only known at run-time.
CodePudding user response:
I turn the reference into a copy to fit std::variant
,
// using std::type_identity for C 20 or later
template <typename T>
struct type_identity {
using type = T;
};
using VType = std::variant<type_identity<Object>,
type_identity<Unrelated>>;
using RType = std::variant<Object, Unrelated>;
static const std::map<TypeEnum, VType> dispatcher = {
{TypeEnum::TYPE_OBJECT, type_identity<Object>{}},
{TypeEnum::TYPE_UNRELATED, type_identity<Unrelated>{}}
};
auto foo(TypeEnum type_enum)
{
Container<Interface> container;
return std::visit([&](auto v) -> RType {
return Read<typename decltype(v)::type>(container, type_enum);
}, dispatcher.at(type_enum));
}