#include<iostream>// function to calculate the greater of two int valuesintmax(intx,inty){return(x>y)?x:y;}// almost identical function to calculate the greater of two double values// the only difference is the type informationdoublemax(doublex,doubley){return(x>y)?x:y;}intmain(){std::cout<<max(5,6);// calls max(int, int)std::cout<<'\n';std::cout<<max(1.2,3.4);// calls max(double, double)return0;}
#include<iostream>// a single function template for maxtemplate<typenameT>Tmax(Tx,Ty){return(x>y)?x:y;}intmain(){std::cout<<max(5,6);// instantiates and calls max<int>(int, int)std::cout<<'\n';std::cout<<max(1.2,3.4);// instantiates and calls max<double>(double, double)return0;}
例如,假设我们正在编写一个程序,其中需要处理一对 int 值,并需要确定这两个数字中哪一个更大。我们可以写这样一个程序:
1 2 3 4 5 6 7 8 91011121314151617181920
#include<iostream>structPair{intfirst{};intsecond{};};constexprintmax(Pairp)// pass by value because Pair is small{return(p.first>p.second?p.first:p.second);}intmain(){Pairp1{5,6};std::cout<<max(p1)<<" is larger\n";return0;}
#include<iostream>structPair{intfirst{};intsecond{};};structPair// compile error: erroneous redefinition of Pair{doublefirst{};doublesecond{};};constexprintmax(Pairp){return(p.first>p.second?p.first:p.second);}constexprdoublemax(Pairp)// compile error: overloaded function differs only by return type{return(p.first>p.second?p.first:p.second);}intmain(){Pairp1{5,6};std::cout<<max(p1)<<" is larger\n";Pairp2{1.2,3.4};std::cout<<max(p2)<<" is larger\n";return0;}
#include<iostream>// A declaration for our Pair class template// (we don't need the definition any more since it's not used)template<typenameT>structPair;// Explicitly define what Pair<int> looks liketemplate<>// tells the compiler this is a template type with no template parametersstructPair<int>{intfirst{};intsecond{};};// Explicitly define what Pair<double> looks liketemplate<>// tells the compiler this is a template type with no template parametersstructPair<double>{doublefirst{};doublesecond{};};intmain(){Pair<int>p1{5,6};// instantiates Pair<int> and creates object p1std::cout<<p1.first<<' '<<p1.second<<'\n';Pair<double>p2{1.2,3.4};// instantiates Pair<double> and creates object p2std::cout<<p2.first<<' '<<p2.second<<'\n';Pair<double>p3{7.8,9.0};// creates object p3 using prior definition for Pair<double>std::cout<<p3.first<<' '<<p3.second<<'\n';return0;}
constexprintmax(Pair<int>p){return(p.first>p.second?p.first:p.second);}constexprdoublemax(Pair<double>p)// okay: overloaded function differentiated by parameter type{return(p.first>p.second?p.first:p.second);}
虽然上述代码可以编译了,但是它没有解决代码冗余的问题。我们实际上希望一个函数能够接受任何类型的参数。换言之我们希望函数可以使用 Pair<T> 类型的形参,其中 T 是一个模板类型参数。因此我们需要使用一个函数模板来完成相应的工作!
下面是一个完整的例子,max()被实现为一个函数模板:
1 2 3 4 5 6 7 8 910111213141516171819202122232425
#include<iostream>template<typenameT>structPair{Tfirst{};Tsecond{};};template<typenameT>constexprTmax(Pair<T>p){return(p.first>p.second?p.first:p.second);}intmain(){Pair<int>p1{5,6};std::cout<<max<int>(p1)<<" is larger\n";// explicit call to max<int>Pair<double>p2{1.2,3.4};std::cout<<max(p2)<<" is larger\n";// call to max<double> using template argument deduction (prefer this)return0;}
max() 函数模板非常直白。因为我们需要向其传递 Pair<T>,所以编译器必须了解 T 是什么。因此,我们需要在函数开头出添加模板参数声明,定义模板类型T。随后,我们就可以使用T作为返回类型,以及模板参数 Pair<T>。
因为 max() 函数的调用基于 Pair<int> 类型实参 ,编译器会基于函数模板实例化函数int max<int>(Pair<int>) ,模板中的 T 被替换为了int。编译器实际上实例化了这样一个函数:
template<typenameT>structFoo{Tfirst{};// first will have whatever type T is replaced withintsecond{};// second will always have type int, regardless of what type T is};
#include<iostream>template<typenameT,typenameU>structPair{Tfirst{};Usecond{};};template<typenameT,typenameU>voidprint(Pair<T,U>p){std::cout<<'['<<p.first<<", "<<p.second<<']';}intmain(){Pair<int,double>p1{1,2.3};// a pair holding an int and a doublePair<double,int>p2{4.5,6};// a pair holding a double and an intPair<int,int>p3{7,8};// a pair holding two intsprint(p2);return0;}
#include<iostream>#include<utility>template<typenameT,typenameU>voidprint(std::pair<T,U>p){std::cout<<'['<<p.first<<", "<<p.second<<']';}intmain(){std::pair<int,double>p1{1,2.3};// a pair holding an int and a doublestd::pair<double,int>p2{4.5,6};// a pair holding a double and an intstd::pair<int,int>p3{7,8};// a pair holding two intsprint(p2);return0;}
#include"pair.h"#include<iostream>voidfoo(){Pair<int>p1{1,2};std::cout<<max(p1)<<" is larger\n";}
main.cpp
1 2 3 4 5 6 7 8 91011121314
#include"pair.h"#include<iostream>voidfoo();// forward declaration for function foo()intmain(){Pair<double>p2{3.4,5.6};std::cout<<max(p2)<<" is larger\n";foo();return0;}