结合std :: is_base_of和std :: enable_if的C ++部分模板专业化 [英] C++ partial template specialization in combination with std::is_base_of and std::enable_if

查看:341
本文介绍了结合std :: is_base_of和std :: enable_if的C ++部分模板专业化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个类别:可序列化可打印

Let's say I have a two classes: Serializable and Printable.

因此,一个简单的模板函数可以接受 Printable 的所有派生类,如下所示:

So a simple template function which accepts all derived classes of Printable could look like:

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;
}

但是,如果我希望它也接受所有<$ c的派生类$ c>可序列化,尽管我仍然可以控制函数体,但这显然行不通:

However, if I want it to accept also all derived classes of Serializable while I still have control over the function body, this would obviously not work:

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 ...



所以我认为剩下的解决方案是模板专业化。

So I figured the remaining solutions for this problem are template specializations.

但是我不知道如何结合<$ c来专业化模板。 $ c> std :: is_base_of 和 std :: enable_if

But I just can't figure out, how I can specialize a template in combination with std::is_base_of and std::enable_if.

我希望有人愿意帮助我!

I hope someone is willing to help me!

推荐答案

尝试逻辑运算符:

std::enable_if<std::is_base_of<Serializable, T>::value ||
               std::is_base_of<Printable, T>::value>::type

您可以轻松地编写可变参数模板,例如:

You can easily write a variadic template like:

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>
{ };






如果您想要其他实现方式:


If you want different implementations:

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 来创建过多的重载候选。

The last overload (the "user-facing" one) should probably be endowed with the above enable_if to not create overly many overload candidates.

您也可以制作一个可变的模板< typename ... Bases> ,其标签如下:

You can probably also make a variadic template <typename ...Bases> with a tag like:

tag_type<std::is_base_of<Bases, T>::value...>

这篇关于结合std :: is_base_of和std :: enable_if的C ++部分模板专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆