假设我有两个类:Serializable
和 Printable
.
所以一个简单的模板函数,它接受 Printable
的所有派生类可能看起来像:
template <class T, class B = Printable, class = typename std::enable_if<std::is_base_of<B, T>::value>::type>
void print(T value) {
cout << value << endl;
}
但是,如果我希望它也接受
Serializable
的所有派生类虽然我仍然可以控制函数体,但这显然行不通:
template <class T, class B = Printable, class = typename std::enable_if<std::is_base_of<B, T>::value>::type>
void print(T value) {
cout << value << endl;
}
template <class T, class B = Serializable, class = typename std::enable_if<std::is_base_of<B, T>::value>::type>
void print(T value) {
cout << value << endl;
}
// Error: Redefinition of ...
所以我认为这个问题的剩余解决方案是模板特化。
但我就是想不通,如何将模板与
std::is_base_of
结合起来专门化一个模板和
std::enable_if
.
我希望有人愿意帮助我!
请您参考如下方法:
尝试逻辑运算符:
std::enable_if<std::is_base_of<Serializable, T>::value ||
std::is_base_of<Printable, T>::value>::type
您可以轻松编写可变参数模板,例如:
is_base_of_any<T, Printable, Serialiable, Googlable, Foobarable>::value
例如:
template <typename T, typename ...> struct is_base_of_any : std::true_type {};
template <typename T, typename Head, typename ...Rest>
struct is_base_of_any<T, Head, Rest...>
: std::integral_constant<bool, std::is_base_of<T, Head>::value ||
is_base_of_any<T, Rest...>::value>
{ };
如果你想要不同的实现:
template <bool...> struct tag_type {};
template <typename T>
void foo(T, tag_type<true, false>) { } // for Printable
template <typename T>
void foo(T, tag_type<false, true>) { } // for Serializable
template <typename T>
void foo(T x)
{
foo(x, tag_type<std::is_base_of<Printable, T>::value,
std::is_base_of<Serializable, T>::value>());
}
最后一个重载(“面向用户”的重载)可能应该被赋予上述
enable_if
不要创建过多的重载候选对象。
你也可以做一个可变参数
template <typename ...Bases>
带有如下标签:
tag_type<std::is_base_of<Bases, T>::value...>