我想知道是否有办法以更好的方式执行以下操作(更容易阅读,更简洁)。
我有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>或类似的东西。
答案 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
来执行此操作。
现在这通常是一个坏主意。以上只做完全匹配。通常如果你有这么多的多态性,你会想把它放到界面中,如果失败了,你可能还有其他一些设计缺陷。
答案 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);