切换取决于对象类型

时间:2015-05-12 16:22:21

标签: c++ c++11

我想知道是否有办法以更好的方式执行以下操作(更容易阅读,更简洁)。

我有Foo的对象具有它具体的Foo实现类型让我们称它们为Foo1 .. FooN。

我还有foo描述的字符串表,例如Foo1"禁止Foo1"。我想要做的是某种类型的检查取决于Foo的实际类型。目前我这样做:

std::string fooUtils::translate(Foo * foo){
   if(typeid(foo) == typeid(Foo1){
      return "bars the Foo1";
   }
   else if
     ...
}

我想知道是否有更好的方法。

我想到的第一个是存储std :: map< std :: typeinfo,std :: string> - 这是我渴望的解决方案,但我不知道将类型信息作为地图的关键(有没有?)的任何副作用。我还想知道是否有任何东西可以用较简洁的方式比较类型,例如boost :: is_type< Foo1,foo>或类似的东西。

3 个答案:

答案 0 :(得分:8)

virtual成员函数的用途是什么:

std::string fooUtils::translate(Foo * foo) {
    foo->translate();
}

使用:

struct Foo {
    virtual std::string translate() const { return "base"; }
};

struct Foo1 : Foo {
    std::string translate() const override {
        return "bars the Foo1";
    }
};

答案 1 :(得分:2)

以下是type_info搜索工具:

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;
}

你做which<A, B, C, D>(*a)并返回实例*a完全(动态)匹配的类型列表中的哪一个。如果找不到匹配项,则会返回type_info const*nullptr来执行此操作。

现在这通常是一个坏主意。以上只做完全匹配。通常如果你有这么多的多态性,你会想把它放到界面中,如果失败了,你可能还有其他一些设计缺陷。

live example

答案 2 :(得分:0)

在此主题中,您可以找到type2enum转换和向后enum2type转换:How to do a typed parameter package class?

答案的摘录:

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