2015-06-20 6 views
2

Я пытаюсь сделать общий код, который вызовет ошибку компиляции, если B не является предком D. То, что я придумал:Шаблон аргумент после оператора разрешения области видимости не замещается

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

Это не работает. Когда я называю 'это так:

assert_base_of<A2,A1>::value; 

Я получаю следующее сообщение об ошибке (г ++ 4.8.2):

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

Похоже, что параметр шаблона D не получает Заменен A1. Может ли кто-нибудь объяснить и предложить решение, пожалуйста?

+0

Что неправильно с 'static_assert (std :: is_base_of :: значение,« B должно быть базой D »)'? –

+0

Мне не разрешено использовать std :: is_base_of, и даже если бы я мог, я все еще хочу знать, почему D не поддается замене :) – pyx

+0

«Разрешено» кем? Если кто-то поставил произвольные ограничения на ваш возможный набор решений, вы должны указать их в вопросе, чтобы избежать потенциально тратить наше время. –

ответ

3

Inheritance не включает производный класс в область базового класса, поэтому нет смысла использовать для этого оператор разрешения области. Правильная альтернатива (которая также работает с множественным наследованием) является злоупотребление правила по разрешению перегрузки:

#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 (не виртуальное наследование), я получаю 0, когда я делаю is_base_of ::стоимость. – pyx

+0

@pyx: вы можете сделать 'is_base_of :: value && is_base_of :: value'. Я думаю, это было бы более правильно названо 'is_direct_base_of'. –

+1

@Veritas: Добро пожаловать в 1k rep! –

Смежные вопросы