C++ 根据对象类型进行切换
我想知道是否有一种方法可以更好地做到以下几点:更容易阅读,更不冗长 我有一个对象Foo,它有具体的Foo实现类型,我们称之为Foo1。。丰 我还有一个描述foo的字符串表,比如Foo1。我想做的是根据实际运行的Foo类型进行某种类型的检查。目前我有:C++ 根据对象类型进行切换,c++,c++11,C++,C++11,我想知道是否有一种方法可以更好地做到以下几点:更容易阅读,更不冗长 我有一个对象Foo,它有具体的Foo实现类型,我们称之为Foo1。。丰 我还有一个描述foo的字符串表,比如Foo1。我想做的是根据实际运行的Foo类型进行某种类型的检查。目前我有: std::string fooUtils::translate(Foo * foo){ if(typeid(foo) == typeid(Foo1){ return "bars the Foo1"; } else if
std::string fooUtils::translate(Foo * foo){
if(typeid(foo) == typeid(Foo1){
return "bars the Foo1";
}
else if
...
}
我想知道是否有更好的办法
我想到的第一个方法是存储std::mapstd::string fooUtils::translate(Foo * foo) {
foo->translate();
}
与:
下面是一个type_信息搜索实用程序:
template<class T, class...Ts>
std::array<std::decay_t<T>, sizeof...(Ts)+1> make_array( T&& t, Ts&&...ts ) {
return {{ std::forward<T>(t), std::forward<Ts>(ts)... }};
}
template<class F, class T, size_t N>
std::array<T, N> sorted( std::array<T, N> arr ) {
std::sort( begin(arr), end(arr), F{} );
return arr;
}
struct p_type_info_sort {
bool operator()( std::type_info const* lhs, std::type_info const* rhs ) const {
return lhs->before(*rhs);
}
};
template<class...Ts, class T>
std::type_info const* which(T const& t) {
static const auto table=sorted<p_type_info_sort>(make_array(
(&typeid(Ts))...
));
auto r = std::equal_range( begin(table), end(table), &typeid(t), p_type_info_sort{} );
if (r.first==r.second) return nullptr;
return *r.first;
}
在该线程中,您可以找到type2enum转换和backward enum2type转换: 答案摘录:
template<class T> type2enum();
#define TYPE2ENUM_SPEC(TYPE, ENUM) \
template<> type2enum<TYPE>() \
{ return ENUM; }
enum { T1enum, T2enum, T3enum }
TYPE2ENUM_SPEC(type1_t, T1enum);
TYPE2ENUM_SPEC(type2_t, T2enum);
TYPE2ENUM_SPEC(some_third_type_t, T3enum);
那么,您将如何遍历所有类型?您需要某种类型的所有可能的子类型的集合?@cerkiewny没有迭代,没有子类型的集合。我们只是在运行时使用动态分派来选择正确的类型。也许我问得不够清楚,但我想继续使用当前的方法,因此以某种方式存储与类型连接的字符串,并根据传入的类型从集合中选择,您提出的方法完全不同。它对我不起作用,因为我需要同时访问所有信息。@Cerkeywny:你说过你想要一种更好的方式,更少的冗长,而且它必须和你现有的代码一样?这没有多大意义。@cerkiewny这确实以某种方式存储了与类型连接的字符串。它也以一种非常高效、简单、不易破坏的方式来实现。您不能将typeinfo直接存储在容器中,因为typeinfo没有公共构造函数。要变得狡猾。在谷歌上搜索type2enum模板函数。它从你的每一个类型和你的类中创建一个枚举,所以你可以在你的切换器中使用这个枚举。我认为它不会起作用,因为子类的数量。。。此外,每次添加子类时,都需要将其添加到which参数列表中。@cerkiewny是吗?您要求在类型之间进行切换。切换需要列出每种情况。哦,我起初没有得到你的答案,所以你只需将std::map修改为std::map,在函数中进行模板选择,然后根据选择的类型信息从std::map中取出字符串?但是你是如何创建std::map的?@cerkiewny啊,我明白了。我的数组只包含typeinfo*这一事实并不重要。我可以解包一个traits类,并在每个条目旁边存储一个class_name::str或一些_func或一些_functor{}。如果某个函数未能编译,或者traits或functor在编译时会生成一个错误,即您缺少某个类的字符串。这实际上比预期的要好,这是一个很好的方法,可以强制创建新类的人为它提供字符串。非常好的解决方案。
template<class T> type2enum();
#define TYPE2ENUM_SPEC(TYPE, ENUM) \
template<> type2enum<TYPE>() \
{ return ENUM; }
enum { T1enum, T2enum, T3enum }
TYPE2ENUM_SPEC(type1_t, T1enum);
TYPE2ENUM_SPEC(type2_t, T2enum);
TYPE2ENUM_SPEC(some_third_type_t, T3enum);