将枚举映射到模板类型



我有一个类型ValueWrapper,它可以存储几种值类型中的一种,由enum标识:

enum class Type : uint32_t
{
Float = 0,
String,
// etc
};
struct ValueWrapper
{
ValueWrapper(float f)
: type{Type::Float},data{std::make_shared<float>(f)}
{}
ValueWrapper(std::string str)
: type{Type::String},data{std::make_shared<std::string>(str)}
{}
Type type;
std::shared_ptr<void> data;
};

现在我想定义一堆函数,以ValueWrapper为参数,并将实际值重定向到另一个函数,例如:

void print(const ValueWrapper &v)
{
switch(v.type)
{
case Type::Float:
std::cout<<*static_cast<float*>(v.data.get());
break;
case Type::String:
std::cout<<*static_cast<std::string*>(v.data.get());
break;
}
}
size_t size_of(const ValueWrapper &v)
{
switch(v.type)
{
case Type::Float:
return sizeof(float);
case Type::String:
return sizeof(std::string);
}
}
template<typename TFrom>
bool is_convertible(Type tTo)
{
switch(tTo)
{
case Type::Float:
return std::is_convertible_v<TFrom,float>;
case Type::String:
return std::is_convertible_v<TFrom,std::string>;
}
}

问题是,我有相当多的类型和函数,我不想为每一个都做一个太长的切换。

是否有一些方法我可以用现代c++做类似的事情(伪代码),所以我只需要做一次切换来确定实际类型?:

type TO_TEMPLATE_TYPE(Type t)
{
switch(t)
{
case Type::Float:
return float;
case Type::String:
return std::string;
}
}
template<typename TFrom>
bool is_convertible(Type tTo)
{
return std::is_convertible_v<TFrom,TO_TEMPLATE_TYPE(tTo)>;
}

using ValueWrapper=std::variant<double,std::string,...>代替。

void print(const ValueWrapper &v)
{
std::visit([](auto const& val){ std::cout<<val; }, v );
}

如果你想要共享所有权逻辑,要么让它成为共享ptr的变体,要么让它成为共享ptr的变体。

我的意思是,你可以重新发明轮子,但是为什么?

如果你完全反对改变布局,接下来我要做的就是创建一个

的变体
template<class T>struct tag_t{using type=T;};
template<class T>constexpr tag_t<T> tag={};

tag_t<double>等,将枚举手动映射到变体,然后使用visit获取tag_t<T>

std::variant<tag_t<double>,tag_t<std::string>> get_tag(Type e){
switch (e){
case Type::Float: return tag<double>;
case Type::String: return tag<std::string>;
}
}

void print(ValueWrapper const& v){
auto tag=get_tag(v.type);
std::visit([&](auto tag){
using T=decltype(tag)::type;
T* p=static_cast<T*>(v.data.get());
std::cout<<*p;
}, tag);
}

这个技术比手动操作要简单100倍;我都做了。

最新更新