在模板函数中获取类型T的父类

时间:2016-12-28 12:54:36

标签: c++ templates inheritance factory-pattern

我想知道模板函数中类型类T的父类是什么,假设我有以下类:

class A{
...
}

class B: public A{
...
}

class C: public B{
...
}


template<typename T>
size_t getBaseHashCode()
{
  return typeid(base_of(T)).hashcode();
}

int main()
{
  A a;
  C c;
  size_t size = getBaseHashCode<C>();// must return hashcode of class B
}

无论如何都要找到类型为T的父类并实现base_of函数?

编辑: 我的确要做的是:

我是为我创建对象的工厂类:

template <typename B>
class Factory{
public:
    template <typename D>
    void registerType(std::string name)
    {
        static_assert(std::is_base_of<B, D>::value, "class doesn't derive from the base");
        table_[name] = &createFunc<D>;
    }
    B* create(std::string name)
    {
        const auto it = table_.find(name);
        if(it != table_.end())
            return it->second();
        FILE_LOG(logERROR) << "unidentified option, acceptable options are:";
        for(auto const &m : list())
            FILE_LOG(logERROR) << '\t' << m;
        return nullptr;
    }

    std::vector<std::string> list()
    {
        std::vector<std::string> lst;
        for(auto const &iter : table_)
            lst.push_back(iter.first);
        return lst;
    }
private:
    template<typename D>
    static B* createFunc()
    {
        return new D();
    }
    typedef B* (*PCreateFunc)();
    std::map<std::string, PCreateFunc> table_;
};
在registerType函数中

我想设置D类型的一些属性或它的父类,然后在create函数中,我想基于它创建对象。

2 个答案:

答案 0 :(得分:1)

您也可以考虑使用一些父包装来自动化typedef

#include <type_traits>
#include <typeinfo>
#include <iostream>

template <class P>
struct base: P {
    using base_type = P;
};

struct A{ };
struct B: base<A>{ };
struct C: base<B>{ };

template <class T>
auto base_of(T) -> typename T::base_type;

template <class T>
using base_of_t = decltype(base_of(std::declval<T>()));

int main() {
    std::cout << typeid(base_of_t<C>).name() << std::endl;
}

输出:

  

1B

c++filt -t 1B的输出:

  

[live demo]

注意它仍然不处理多重继承

答案 1 :(得分:0)

您可以使用一些您不必定义的函数声明 它遵循一个最小的工作示例:

#include<utility>
#include<typeinfo>
#include<iostream>

class A{};
class B: public A{};
class C: public B{};

B base_of(const C &);
A base_of(const B &);

template<typename T>
void getBaseHashCode() {
    std::cout << typeid(decltype(base_of(std::declval<T>()))).name() << std::endl;
}

int main() {
    getBaseHashCode<B>();
    getBaseHashCode<C>();
}

它利用了这样一个事实:在这种情况下,你在调用期间有完全匹配。它是一个相当弱的解决方案,但可以使用问题中的示例代码。

那就是说,我同意整个问题看起来像一个XY问题。

修改

正如@ Jarod42在评论中提到的那样,一种更惯用(和冗长)的方式是使用特征。
它遵循一个最小的工作示例:

#include<typeinfo>
#include<iostream>

class A{};
class B: public A{};
class C: public B{};

template<typename> struct base_of;
template<> struct base_of<B> { using type = A; };
template<> struct base_of<C> { using type = B; };

template<typename T>
void getBaseHashCode() {
    std::cout << typeid(typename base_of<T>::type).name() << std::endl;
}

int main() {
    getBaseHashCode<B>();
    getBaseHashCode<C>();
}

这也将解决由于多重继承而导致的问题。 base_of专业化的设计者将负责将其中一个基类推广到首选的角色。