2015-06-20 91 views
2

我試圖做一個通用的代碼,會導致編譯錯誤,如果B不是D的祖先我想出什麼樣的主意:模板參數不取代

template<typename B, typename D> 
struct assert_base_of { 
    enum {value = sizeof(B::D)}; 
} 

它不起作用。當我稱之爲'像這樣:

assert_base_of<A2,A1>::value; 

我得到以下錯誤(G ++ 4.8.2):

main.cpp:16:22: error: ‘D’ is not a member of ‘A2’ 

它看起來像模板參數d沒有得到取代A1。任何人都可以解釋並提出解決方案嗎?

+0

什麼'static_assert錯誤(std :: is_base_of :: value,「B必須是D的基數」)? –

+0

我不允許使用std :: is_base_of,即使可以,我仍然想知道爲什麼D不會被替換:) – pyx

+0

「允許」由誰?如果有人對你可能的解決方案集進行了任意限制,你應該在問題中說明它們,以避免浪費我們的時間。 –

回答

3

繼承不會將派生類封裝到基類的作用域,因此使用作用域解析運算符是沒有意義的。正確的選擇(也可與多重繼承)是濫用重載決策規則:

#include <iostream> 
#include <type_traits> 

template<typename Base, typename Derived, 
     bool = std::is_same<Base, Derived>::value> 
struct is_base_of_impl 
{ 

    typedef typename std::remove_cv<Base>::type  no_cv_base;  
    typedef typename std::remove_cv<Derived>::type no_cv_derived; 


    template<typename _Up> 
    static std::true_type test(no_cv_derived&, _Up); 
    static std::false_type test(no_cv_base&, int); 

    //Black Magic 
    struct converter 
    { 
    operator no_cv_derived&(); 
    operator no_cv_base&() const; 
    }; 

    static const bool value = decltype(test(converter(), 0))::value; 
}; 

template<typename Base, typename Derived> 
struct is_base_of_impl<Base, Derived, true> 
{ 
    static const bool value = std::is_same<Base, Derived>::value; 
}; 

template<typename Base, typename Derived> 
struct is_base_of 
: public std::integral_constant<bool, 
       is_base_of_impl<Base, Derived>::value> 
{ }; 


struct A {}; 
struct B1 : A {}; 
struct B2 : A {}; 
struct C : B1, B2 {}; 

int main() 
{ 
    std::cout << is_base_of<A, B1>::value << "\n"; 
    std::cout << is_base_of<B1, C>::value << "\n"; 
    std::cout << is_base_of<A, C>::value << "\n"; 
    return 0; 
} 

欲瞭解更多信息,看看到這些鏈接:

How does `is_base_of` work?

https://groups.google.com/d/msg/comp.lang.c++.moderated/xv4VlXq2omE/--WAroYkW2QJ

+0

我可能是錯的,但經過測試,我認爲你的解決方案不適用於多繼承 - 如果A繼承自B1和B2,並且都從C繼承(非虛擬繼承),那麼當我做is_base_of ::值。 – pyx

+0

@pyx:不過,你可以做'is_base_of :: value && is_base_of :: value'。我想這應該更恰當地稱爲「is_direct_base_of」。 –

+1

@Veritas:歡迎來到1k代表! –