特化和偏特化

Partial Template Specialization能够让你在模板(Template)的所有可能的实体中特化出一组子集.

  1.模板的特化(template specialization):

    例如,定义如下的一个模板:
    template<class Window, class Controller>
    class Widget
    {
      ... 泛化实现代码 ...
    };
    然后你可以像下面那样明确地加以特化:
    template<>    //注意:template后面的尖括号中不带任何内容;
    class Widget<ModalDialog, MyController>
    {
      ... 特化实现代码 ...
    };
    其中ModalDialog和MyController是你自己另外定义的类;有了这个Widget的特化定义之后,如果你以后定义了Widget<ModalDialog, MyController>对象时,编译器就会使用上述的特化定义,如果定义了其它泛型对象,那么编译器就是用原本的泛化定义;这就是模板的特化.

  2.Partial Template Specialization(模板偏特化)

从英文单词可看出意思为:模板部分物化."偏"实在不是一个明智的译法,就像偏导数一样,非得看定义才能明白,完全没采用中文本意来翻译.

模板特化是通过"给模板中的所有模板参数一个具体的类"的方式来实现的.而模板偏特化则是通过"给模板中的部分模板参数以具体的类,而留下剩余的模板参数仍然使用原来的泛化定义"的方式来实现的;
    比如,就上面的Widget类模板的定义来说,有时候想针对任意的Window来搭配一个特定的MyController类特化Widget,这个时候就需要使用模板偏特化机制了.下面的Widget类模板就是Widget的偏特化定义:
    template<class Window>                        //仍然使用原来的泛化定义;
    class Widget<Window, MyController>            //MyController是具体的类,是特化定义;
    {
      ... 偏特化实现代码 ...
    };
    这就是一个偏特化定义;一个MyController类可以搭配任意一种Window.
    通常在一个类模板的偏特化定义中,你只会特化某些模板参数而留下其它泛化参数.当你在程序中具体实现上述类模板的时,编译器会试着找出最匹配的模板定义.这个寻找过程十分复杂精细,允许你以富有创意的方式来进行偏特化.例如,假设你有一个Button类模板,它有一个模板参数,那么,你不但可以拿任意的Window搭配特定的MyController来特化Widget,还可以拿任意Button搭配特定的MyController来偏特化Widget:
    template<class ButtonArg>
    class Widget<Button<ButtonArg>, MyController>    //使用任意Button搭配具体的类MyContorller
    {
      ... 偏特化实现代码 ...
    };
    模板的偏特化能力很强大.当你实例化一个模板时,编译器会把目前存在的偏特化模板和全特化模板做比较,并找出其中最合适、最匹配的实现.这样,灵活性就很大.但是不幸的是,
模板的偏特化机制不能用在函数身上,不论成员函数还是非成员函数.

  注意:
  1.虽然你可以全特化类模板中的成员函数,但是你不能偏特化他们;
  2.你不能偏特化命名空间级别(namespace-level)的函数(non-member).最接近"命名空间级别模板函数"的偏特化机制就是函数重载,那就意味着你对"函数参数"(而非返回值类型或内部所用类型)有很精致的特化能力;
  3.特化或全特化时,template后面的尖括号中不带任何内容;

  总结:
模板特化/全特化是指给每一个模板参数一个具体的类型,以具体实现这个模板,而且template后面的尖括号中不带任何内容;

模板偏特化是指只给部分模板参数一个具体的类型,来实现这个模板;


附:模板特化,全特化,偏特化,全部特化,部分特化的含义

这几个名词真是把人搞混了(是因为有的著作,甚至名著以讹传讹),我最近整理了以下,看看大家的意见如何。

模板特化:任何针对模板参数进一步进行条件限制设计的特化版本。《泛型思维》

全特化就是全部特化,即针对所有的模板参数进行特化。《c++ primer》
偏特化就是部分特化,即针对部分模板参数进行特化。《c++ primer》

全特化和偏特化的定义不是很严格,所以有的时候不容易让人理解。

举例如下:
template<class U,class T>
class C{};
全特化:
template<>
class C<int,char>{};
偏特化:
template<class U>
class C<U,int>{};
大家应该对上面的例子应该没有什么异议吧。

再看下面的一个例子:
template<class T,class U>
class C<T*,U*>{};
这属于全特化还是偏特化呢?一般大部分人都认为是偏特化,但是按照上面的定义似乎应该是全特化(所有的模板参数都特化了呀)。

我觉得没有必要在名词上作口舌之争,全特化也好,偏特化也好,只要我们掌握它的意义即可。折中的来看,我认为就可以称之为模板特化,毕竟它符合模板特化的含义。

顺便说一下:《c++ primer》这本书没有很好的说明全特化和偏特化的含义,造成很多的歧义,我对这个问题也是迷茫了好久。

规范的原文是这样的:

The standard term explicit specialization refers to a language feature that we call full specialization instead. It provides an implementation for a template with template parameters that are fully substituted: No template parameters remain. Class templates and function templates can be fully specialized. So can members of class templates that may be defined outside the body of a class definition (i.e., member functions, nested classes, and static data members).


C++中,模板是一种通用的编程工具,可以在编译时生成不同类型的代码。特化特化是模板的两种特殊形式,用于定制模板在特定类型或条件下的行为。 特化是指为模板提供一个特定类型的实现,当模板被实例化时,编译器会优先选择特化版本。特化版本可以完全替代通用版本,通常用于优化性能或处理特殊情况。 特化是指为模板提供一个部分特化的实现,当模板被实例化时,编译器会根据匹配度选择特化版本或通用版本。特化版本不能完全替代通用版本,通常用于处理复杂类型或多个参数的情况。 以下是特化特化的示例: 特化示例: ```cpp template <typename T> class MyTemplate { public: void myFunc() { std::cout << "This is the generic version." << std::endl; } }; template<> class MyTemplate<int> { public: void myFunc() { std::cout << "This is the specialized version for int." << std::endl; } }; int main() { MyTemplate<double> myDoubleObj; myDoubleObj.myFunc(); // This is the generic version. MyTemplate<int> myIntObj; myIntObj.myFunc(); // This is the specialized version for int. return 0; } ``` 在上面的示例中,MyTemplate类有一个通用版本和一个特化版本,当模板实例化为int类型时,编译器会选择特化版本,输出特定的信息。 特化示例: ```cpp template <typename T, typename U> class MyTemplate { public: void myFunc() { std::cout << "This is the generic version." << std::endl; } }; template <typename T> class MyTemplate<T, int> { public: void myFunc() { std::cout << "This is the partial specialization for T and int." << std::endl; } }; int main() { MyTemplate<int, double> myObj1; myObj1.myFunc(); // This is the generic version. MyTemplate<double, int> myObj2; myObj2.myFunc(); // This is the partial specialization for T and int. return 0; } ``` 在上面的示例中,MyTemplate类有一个通用版本和一个特化版本,当模板实例化为T和int类型时,编译器会选择特化版本,输出特定的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值