Статическое подтверждение для публичного наследования

Я построил вспомогательный класс, который создавал бы пользовательский класс с помощью шаблонов, этот пользовательский класс должен наследовать от определенного класса, я могу проверить это с помощью std::is_base_of.

Однако мне также нужно проверить, является ли наследование общедоступным, как это можно достичь?

Для справки, вот урезанная версия класса, у меня есть 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()
    {
    }       
};

Ответ 1

Благодаря Quentin и cpplearner для указания меня в правильном направлении. Я нашел, что ответ Quentins работает нормально, если утверждение должно пройти, но в случае сбоя static_assert не поймает ошибку, вместо этого он будет сгенерирован внутри шаблона, удалив выгода от четкого сообщения static_assert.

Затем cpplearner упомянул std::is_convertible, который я пытался использовать раньше, но забыл о необходимости *, а также B и D, казалось, были неправильный путь.

Все это привело меня к созданию:

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

Что, похоже, выполняет эту работу, ниже приведен полный код в качестве полного примера.

#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");
}

Ответ 2

Насколько я знаю, публичное наследование является единственным случаем, когда может выполняться неявное преобразование указателя (референсное преобразование может быть достигнуто с помощью перегруженного оператора).

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*>()));

Посмотрите вживую на Coliru