2016-06-18 32 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