C++ 根据对象类型进行切换

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

我想知道是否有一种方法可以更好地做到以下几点:更容易阅读,更不冗长

我有一个对象Foo,它有具体的Foo实现类型,我们称之为Foo1。。丰

我还有一个描述foo的字符串表,比如Foo1。我想做的是根据实际运行的Foo类型进行某种类型的检查。目前我有:

std::string fooUtils::translate(Foo * foo){
   if(typeid(foo) == typeid(Foo1){
      return "bars the Foo1";
   }
   else if
     ...
}
我想知道是否有更好的办法

我想到的第一个方法是存储std::map——这是我热衷的解决方案,但我不知道将类型信息作为映射键会有什么副作用,有没有?。我还想知道是否有什么东西可以用不太详细的方式比较类型,例如boost::is_type或类似的东西。

这就是虚拟成员函数的用途:

std::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);