Skip to main content
 首页 » 编程设计

templates之C++ 部分模板特化结合 std::is_base_of 和 std::enable_if

2024年11月01日12birdshome

假设我有两个类:SerializablePrintable .

所以一个简单的模板函数,它接受 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...>