Шаблон с проверкой типа

Подскажите пожалуйста, как в шаблоне функции сделать проверку типа шаблона-аргумента. Например, есть такой набор классов и есть шаблонная функция:

class Base { ... }
class Derived1 : B { ... }
class Derived2 : B { ... }
class Other { ... }

template <typename T> void foo(T arg) { ... }

В шаблонной функции на этапе компиляции надо проверить, что arg является объектом класса Base, или класса-потомка Base (т.е. Derived1 или Derived2). Иначе говоря, надо проверить является ли T классом Base, или классом, унаследованным от Base. Если это так, то все нормально. Иначе надо выдать ошибку компиляции с соответствующей диагностикой.

В <type_traits> нашёл функцию template<class Base, class Derived> struct is_base_of, которая выполняет такую проверку, но как ее использовать в моем случае, не понимаю.

Например, использовать его с std::enable_if
template <typename T, typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>*>
void foo(T arg) { }

Также стоит учесть, что приватное наследование за пределами класса не видно. У Вас в коде наследование именно приватное.

template <typename T, typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>*> 
void foo(T arg) { }

Спасибо. Работает! Только не понимаю как.
Под Visual Studio 2017 видит даже приватное наследование.

Только не понимаю как.

Что именно не понятно?

Под Visual Studio 2017 видит даже приватное наследование.

std::is_base_of видит приватное наследование.
Я к тому, что далее, например, если попробовать создать указатель на базовый класс и присвоить ему адрес наследника, то будут проблемы:

#include <type_traits>

class Base {};
class PublicDerived : public Base {};
class PrivateDerived : Base {};

template <typename T, typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>*> 
void foo(T arg) 
{ 
    Base *p = &arg;//Если T приватный наследник Base, то будет ошибка.
}

int main()
{
    foo(Base());//ok
    foo(PublicDerived());//ok
    foo(PrivateDerived());//Ошибка в foo при инициализации указателя p
    //...
}

Непонятно вот это

template <typename T, typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>*>

Что здесь происходит, и как это работает.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.