2016-12-28 18 views
1

Я хочу, чтобы выяснить, что является родителем в функции шаблона класса типа 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?

Edit: действительно то, что я хочу сделать, это:

Я завод класс, который создает объекты для меня:

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, я хочу создать на нем объекты.

+0

Зачем вам это нужно? Похоже на XY-проблему для меня. –

+2

Что делать с множественным наследованием? – Quentin

+0

У меня есть заводский класс (на основе абстрактного шаблона фабричного проектирования), который при создании объектов проверяет свойство в нем или его родителей, а затем на него (значение свойства) создает объект. поэтому я хочу знать, что это за тип и каков тип его родителей. – abdolahS

ответ

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

использует тот факт, что в этом случае у вас есть точные совпадения во время invokations. Это довольно слабое решение, но работает с примером кода в вопросе.


Таким образом, я согласен с тем, что весь вопрос выглядит как проблема XY.

EDIT

Как упомянуто @ 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 специализации будет отвечать за продвижение одного из базовых классов на роль предпочтительного номера.

+0

спасибо, но кажется, что это не очень хороший дизайн для проектов с множеством модулей и классов! – abdolahS

+1

@abdolahS Вот почему мои комментарии после кода. – skypjack

+1

Создание пользовательских признаков кажется более идиоматичным: 'template <> struct base_of {using type = B;};' даже если более подробный ... – Jarod42

0

Вы могли бы также рассмотреть возможность использования некоторых родительских оберток для автоматизируют typedef Ing:

#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:

B

[live demo]

Примечание она по-прежнему не имеет дело с множественным наследованием