Template 特化
来源:互联网 发布:ae2015 mac破解补丁 编辑:程序博客网 时间:2024/06/05 22:12
转:https://www.ibm.com/developerworks/community/blogs/12bb75c9-dfec-42f5-8b55-b669cc56ad76/entry/c__e6_a8_a1_e6_9d_bf__e7_a9_b6_e7_ab_9f_e4_bb_80_e4_b9_88_e6_98_af_e7_89_b9_e5_8c_96?lang=en
我已经制定了一个计划,希望可以定期地在博客上更新文章。我将探讨编译 器如何处理模板等这类有意思的事情,并佐以实例。
struct t1{}; struct t2{}; struct t3{};void func(t1 arg){ printf(" called t1\n" ); }void func(t2 arg){ printf(" called t2\n" ); }void func(t3 arg){ printf(" called t3\n" ); }int main(void){t1 x1; t2 x2; t3 x3;func(x1);func(x2);func(x3);return 0;}
called t1
called t2
called t3
void func(t1); void func(t2); void func(t3);
#include < iostream> #include < typeinfo> struct t1{}; struct t2{}; struct t3{};using namespace std;template < class A, class B, class C> void func(A a1, B a2, C a3){ cout < < " A: " < < typeid(a1).name() < < endl; cout < < " B: " < < typeid(a2).name() < < endl; cout < < " C: " < < typeid(a3).name() < < endl;}int main(void){ t1 x1; t2 x2; t3 x3; func(x1,x2,x3); return 0;}
#include < iostream> #include < typeinfo> using namespace std;struct t1{}; struct t2{}; struct t3{};template < class A, int I> struct container{ void callMe(){ cout < < " primary A: " < < typeid(A).name() < < " I: " < < I < < endl; }};int main(void){ container< t1,10> test; test.callMe(); return 0;}
在这个例子中,编译器并不会玩什么把戏,这个例子中只有一个类container, 它接收了实参<t1,10>并传递给模板参数<A, I>,推导出A即为t1,I为10。
再看:
#include < iostream> #include < typeinfo> using namespace std;struct t1{}; struct t2{}; struct t3{};template < class A, int I> struct container{ void callMe(){ cout < < " primary A: " < < typeid(A).name() < < " I: " < < I < < endl; }};template < > struct container< t3,99> { void callMe(){ cout < < " complete specialization t3, 99" < < endl; }};int main(void){ container< t1,10> test1; test1.callMe(); container< t3,99> test2; test2.callMe(); return 0;}
在这个例子中有两个模板,其中一个是全特化模板,即模板中模板参数全部指定为确定的类型。特化(specialized)不过是一个花哨的术语,意思是形参不再为形参,它们已经有了确定的值。我更倾向于使用“全特化”这个术语,感觉这更容易让人理解。但是在大多数的C++书籍,包括标准C++,都将其称为“显示特化”。
现在编译器有了两个类名都为container的类模板,类模板被重载:
- 候选模板1可推出 <A=t1, I=10> ,所以候选模板1有效;
现在编译器有了两个类名都为container的类模板,类模板被重载:
- template <
class A, int I> struct container; template < > struct container< t3,99> ;
- 候选模板1可推出 <A=t1, I=10> ,所以候选模板1有效;
- 候选模板2无法推出<t3,99> 能与 <t1,10>匹配,所以候选模板2被剔除。
这样编译器只有一个候选模板1,也即最终被匹配的模板。
当编译器执行到container<t3, 99>test2,对于参数<t3, 99>:
- 候选模板1可推出<A=t3, I=99>,所以候选模板1有效
当编译器执行到container<t3, 99>test2,对于参数<t3, 99>:
- 候选模板1可推出<A=t3, I=99>,所以候选模板1有效
- 候选模板2,很明显 <t3,99> 与模板中的 <t3,99>相匹配,所以候选模板2有效。
当在一个程序中发现有两个或者两个以上候选模板有效时,编译器根据最匹配原则选择最为匹配的那个模板,即候选模板2。
下一个例子:
下一个例子:
#include <
iostream> #include < typeinfo> using namespace std;struct t1{}; struct t2{}; struct t3{};template < class A, int I> struct container{ void callMe(){ cout < < " primary A: " < < typeid(A).name() < < " I: " < < I < < endl; }};template < class A1> struct container< A1,25> { void callMe(){ cout < < " partial specialization" < < typeid(A1).name() < < " and 25 " < < endl; }};template < > struct container< t3,99> { void callMe(){ cout < < " complete specialization t3, 99" < < endl; }};int main(void){ container< t1,10> test1; test1.callMe(); container< t3,99> test2; test2.callMe(); container< t2,25> test3; test3.callMe(); container< t3,25> test4; test4.callMe(); return 0;}
template < class A, int I> struct container; template < class A1> struct container< A1,25> ; template < > struct container< t3,99> ;
模板1是带有两个模板参数的主模板,模板2是带有一个模板参数的偏特化模板,模板3是无模板参数的全特化模板。
如前面所说,偏特化也仅是一个花哨的术语,偏特化模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。
当编译器编译执行到container<t3,25> test4 ,参数为<t3,25>:
- 候选模板1,编译器可推导出 <A=t3, I=25>,故候选模板1有效;
- 候选模板2,编译器为偏特化模板可推导出 <A1=t3, 25>,故候选模板2有效;
- 候选模板3, 编译器不可能从 <t3,25> 得到 <t3,99>,故候选模板3被剔除。
当编译器编译执行到container<
- 候选模板1,编译器可推导出 <
- 候选模板2,编译器为偏特化模板可推导出
- 候选模板3, 编译器不可能从
候选模板2是最匹配的模板,故匹配模板2。
下面的例子有一些微小的变化:
下面的例子有一些微小的变化:
#include < iostream> #include < typeinfo> using namespace std;struct t1{}; struct t2{}; struct t3{};template < class A, int I> struct container{ void callMe(){ cout < < " primary A: " < < typeid(A).name() < < " I: " < < I < < endl; }};template < int I1> struct container< t3,I1> { void callMe(){ cout < < " partial specialization t3 and " < < I1 < < endl; }};template < > struct container< t3,99> { void callMe(){ cout < < " complete specialization t3, 99 " < < endl; }};int main(void){ container< t1,10> test1; test1.callMe(); container< t3,99> test2; test2.callMe(); container< t3,75> test3; test3.callMe(); container< t3,25> test4; test4.callMe(); return 0;}
本质上,偏特化模板的匹配和选择过程与重载解析非常类似。实际上,在非常复杂的偏特化情况下,编译器可能就是将偏特化直接译成函数,然后直接调用重载解析来处理。
重载解析和偏特化匹配都用到了模板参数推导。
重载解析和偏特化匹配都用到了模板参数推导。
0 0
- Template 特化
- Template的偏特化
- template-模板完全特化
- template的特化
- 模板特化(template specialization)
- c++ template 类模板特化
- C++ Template Specialization (模板特化)
- 【C++模板】特化与偏特化 template [partial] specialization
- 通过VC++ STL源码了解template特化与偏特化
- Template function无法偏特化及其解决方法.
- C++ template学习笔记之模板特化
- 模板显式特化之template<>语法
- 模板特化和偏模板特化例子(template specialization and partial template specialization)
- C++ 函数模板的特化(Function Template Specialization)
- C++笔记(8) template partitial specialization模板偏特化
- 特化
- Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧
- Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧
- 线性代数学习笔记
- 一个简单的 A 星算法的实现
- Visual Studio 各版本下载
- 解决wordpress下编辑jpg格式图片的问题
- php memcache分布式和要注意的问题
- Template 特化
- cubieboard + busybox 打造mini系统
- JSONP获取Twitter和Facebook文章数
- struct赋值时带成员名称
- Binary Tree Level Order Traversal - LeetCode
- Xcode 5关闭ARC
- Nginx虚拟主机配置实例(Nginx VirtualHost Example)
- introduction to CUDA
- 游戏开发-3D基础