2017-05-24 14 views
10

Zbudowałem klasę pomocniczą, która tworzyła niestandardową klasę za pośrednictwem szablonów, ta niestandardowa klasa musi dziedziczyć z określonej klasy, mogę to sprawdzić za pomocą std::is_base_of.Statyczny aser dla dziedziczenia publicznego

Muszę jednak sprawdzić, czy dziedziczenie jest publiczne, w jaki sposób można to osiągnąć?

Dla odniesienia, tutaj jest obnażona wersja klasy, mam tam std::is_base_of.

template<class CustomSink> 
class Sink 
{ 
    static_assert(std::is_base_of<BaseSink, CustomSink>::value, "CustomSink must derive from BaseSink"); 
    //Some static assert here to check if custom sink has publicly inherited BaseSink 
    //static_assert(is_public..... 
public: 
    template<class... Args> 
    Sink(Args&&... args) 
    { 
    } 
    ~Sink() 
    { 
    }  
}; 

Odpowiedz

1

Dzięki zarówno Quentin i cpplearner dla wskazujące mnie we właściwym kierunku. Znalazłem Quentins odpowiedź działała dobrze, jeśli asercja powinna przejść, ale w przypadku nieudanego przypadku static_assert nie złapałby błędu, zamiast tego zostałby wygenerowany wewnątrz szablonu, usuwając korzyści z czystej wiadomości static_assert.

Następnie cpplearner wymienione std::is_convertible, które próbowałem użyć wcześniej, ale zapomniałem o konieczności *, również B i D wydawało się być w odwrotnym kierunku.

Wszystko to prowadzi mnie do tworzenia:

static_assert(std::is_convertible<Derived*, Base*>::value, "Derived must inherit Base as public"); 

co wydaje się wykonać zadanie, poniżej jest pełny kod jako kompletny przykład.

#include <type_traits> 

class Base { }; 
class Derived : Base { }; 
class DerivedWithPublic : public Base { }; 

int main() { 
    static_assert(std::is_convertible<DerivedWithPublic*, Base*>::value, "Class must inherit Base as public"); 
    static_assert(std::is_convertible<Derived*, Base*>::value, "Derived must inherit Base as public"); 
} 
9

O ile mi wiadomo, dziedziczenie publiczne to jedyny przypadek, gdy wskaźnik niejawna konwersja może być przeprowadzona (konwersja odniesienia mógłby zostać osiągnięty poprzez przeciążonego operatora).

template <class T> 
std::true_type is_public_base_of_impl(T*); 

template <class T> 
std::false_type is_public_base_of_impl(...); 

template <class B, class D> 
using is_public_base_of = decltype(is_public_base_of_impl<B>(std::declval<D*>())); 

See it live on Coliru

+3

Lub po prostu użyć 'std :: is_convertible '? – cpplearner

Powiązane problemy