Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static Assert for Public Inheritance

I built a helper class that would construct a custom class via templates, this custom class must inherit from a certain class, I can check for this with std::is_base_of.

However I also need to check that the inheritance is public, how can this be achieved?

For reference, here is a stripped down version of the class, I have the std::is_base_of in there.

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()
    {
    }       
};
like image 804
Thomas Monkman Avatar asked May 24 '17 12:05

Thomas Monkman


2 Answers

As far as I know, public inheritance is the only case where an implicit pointer conversion can be performed (a reference conversion could be achieved via an overloaded operator).

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

like image 148
Quentin Avatar answered Oct 30 '22 11:10

Quentin


Thanks to both Quentin and cpplearner for pointing me in the right direction. I found Quentins answer worked fine if the assert should pass, but on a failed case the static_assert would not catch the error, instead it would be generated inside the template, removing the benefit of the clear static_assert message.

Then cpplearner mentioned std::is_convertible which I had tried to use before but had forgotten about needing the *, also the B and D seemed to be the wrong way round.

All of this lead me to creating:

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

Which seems to do the job, below is the full code as a complete example.

#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");
}
like image 39
Thomas Monkman Avatar answered Oct 30 '22 11:10

Thomas Monkman