Статическое подтверждение для публичного наследования
Я построил вспомогательный класс, который создавал бы пользовательский класс с помощью шаблонов, этот пользовательский класс должен наследовать от определенного класса, я могу проверить это с помощью 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