2015-06-20 96 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代表! –