调用仅允许子类作为参数的模板化方法
Calling a templated method allowing only subclasses as parameter
假设我有一组 类 继承自单个超类 S:
class S{ ... };
class C1 : public S{ ... };
class C2 : public S{ ... };
那么假设我有一个模板化方法:
template<class T> void foo(T* instance);
我想静态检查 foo 从未被调用以提供超类的实例,而仅被调用以提供(具体的)子类之一(例如显式调用 foo<C1>(x)
)
这可能吗?
首先我们可以写一个特征来检查 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");
}
这会给你一个更好的错误,但我个人认为函数的类型约束属于声明。
假设我有一组 类 继承自单个超类 S:
class S{ ... };
class C1 : public S{ ... };
class C2 : public S{ ... };
那么假设我有一个模板化方法:
template<class T> void foo(T* instance);
我想静态检查 foo 从未被调用以提供超类的实例,而仅被调用以提供(具体的)子类之一(例如显式调用 foo<C1>(x)
)
这可能吗?
首先我们可以写一个特征来检查 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");
}
这会给你一个更好的错误,但我个人认为函数的类型约束属于声明。