2016-06-18 33 views
1

假设衍生我有一个类,像这样:获得基地

template<class T> 
class Base{ }; 

假设我有另一个类,像这样:

template<class T, class Other> 
class Derived : 
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ }; 

是否有某种方式来创建一个模板类,以确定哪个版本Base(如果有的话)像Derived这样的随机类是派生自?

+0

你可以简单地在Derived中提供一个'typedef'。 –

+0

@ Cheersandhth.-Alf这是真实的....但我懒惰,不想重写一吨代码(所有想法可能是我倒退) – DarthRubik

+0

另一种方法是编译所有可能的' T'类型。更多的工作。 –

回答

2

这里是一个可能的解决方案(因为C++ 11的工作 - 好,它的工作原理与C++ 14,但它与C++ 11做的,如果你使用Base<T>,而不是auto作为返回类型为f) :

#include<utility> 
#include<type_traits> 

template<class T> 
class Base{ }; 

template<class T> 
class OtherRandomClass{ }; 

template<class T, class Other> 
class Derived : 
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ }; 

template<typename T> 
constexpr auto f(const Base<T> &b) { return b; } 

template<typename T> 
struct S { 
    using type = decltype(f(std::declval<T>())); 
}; 

int main() { 
    static_assert(std::is_same<typename S<Derived<int, double>>::type, Base<int>>::value, "!"); 
} 

如果Derived继承比Base一次它不工作。
使用sfinae(类似于void_t成语),甚至可以设计一个类似于enable_if的类:它只有在T实际上从Base继承一次时才具有type
这将有以下形式:

template<typename T> 
constexpr auto f(const Base<T> &b) { return b; } 

template<typename...> 
using void_t = void; 

template<typename T, typename = void_t<>> 
struct S { }; 

template<typename T> 
struct S<T, void_t<decltype(f(std::declval<T>()))>> { 
    using type = decltype(f(std::declval<T>())); 
}; 

这个结构可以在编译时对任何模板欺骗你能想象的使用。

在这两种情况下,S::type(如果存在)是Derived继承的基类的类型,即Base<T>
有关详细信息,请参见main函数中的static_assert

+1

酷....这正是我所需要的!!!!!我没有想过用数据挖掘功能 – DarthRubik

+0

@DarthRubik实际上它很棘手。我不知道它会工作,直到我尝试它! :-) – skypjack

+1

也给了我''void_t'怪异世界的崩溃过程 – DarthRubik

1
#include <iostream> 
#include <typeinfo> 

// placeholder template 
template<class SomeDerived> struct traits {}; 

template<class T> 
class Base{ }; 

template<class T> 
class OtherRandomClass{ }; 

template<class T, class Other> 
class Derived : 
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ }; 


// specialise for our class to provide introspection 
template< 
    class T1, 
class T2> 
struct traits< 
    Derived<T1, T2> 
    > 
{ 
    using t1_type = T1; 
    using first_base_type = Base<T1>; 
}; 

int main() 
{ 
    Derived<int, float> x; 

    using mytraits = traits<decltype(x)>; 
    std::cout << typeid(mytraits::t1_type).name() << std::endl; 
    std::cout << typeid(mytraits::first_base_type).name() << std::endl; 
} 
+0

哇。如此简单,我使用了这样一个复杂的解决方案!唯一的缺点是,这只适用于“派生”,或者至少需要为每个想要检测基类的类提供专门化。不确定这是OP所要求的。在他提到的评论中,另一个类从哪里尝试继承_... – skypjack

+0

@skypjack是的,你坚持不得不为你想要反思的每个类(或模板)的形状产生特征。我的感觉是,经常伸出这样的代码是设计错误的结果。 –

+0

当然,我不想讨论设计决策背后的原因,我只是试图回答OP。谢谢您的回复。 – skypjack