Вызов шаблонного метода, допускающего только подклассы в качестве параметра
Предположим, у меня есть набор классов, унаследованных от одного суперкласса S:
class S{ ... };
class C1 : public S{ ... };
class C2 : public S{ ... };
Тогда предположим, что у меня есть шаблонный метод:
template<class T> void foo(T* instance);
Я хотел бы статически проверить, что foo никогда не вызывается, предоставляя экземпляр суперкласса, а только вызывается, предоставляя один из (конкретных) подклассов (например, явно вызывая foo<C1>(x)
например)
Это возможно?
1 ответ
Решение
Сначала мы можем написать черту, чтобы проверить, T
происходит от S
, но нет S
:
template <class Base, class Derived>
using is_strict_base =
std::integral_constant<bool,
std::is_base_of<Base,Derived>::value &&
!std::is_same<Base,typename std::remove_cv<Derived>::type>::value>;
Ты можешь использовать std::enable_if
использовать эту черту:
template<class T>
typename std::enable_if<is_strict_base<S,T>::value>::type
foo(T* instance)
{}
С C++14 вы можете использовать std::enable_if_t
чтобы сделать его немного красивее:
template<class T>
std::enable_if_t<is_strict_base<S,T>::value>
foo(T* instance)
{}
Другой вариант заключается в использовании static_assert
:
template<class T>
void foo(T* instance)
{
static_assert(is_strict_base<S,T>::value,
"T must be derived from S, but not S");
}
Это дает вам более приятную ошибку, но я лично считаю, что ограничения типа для функции принадлежат объявлению.