一:函数模版和特化模版的引用
1.首先考虑特化函数模版的参数
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
template<>
int compare(const int& ls,const int& rs)
{
std::cout<<"first \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int first1(1),first2(2);
int &second1(first1);
int &second2(first2);
const int &third1(first1);
const int &third2(first2);
int r(0);
r = compare(first1,first2);
std::cout<<r<<'\n';
r = compare(second1,second2);
std::cout<<r<<'\n';
r = compare(third1,third2);
std::cout<<r<<'\n';
r = compare(3,2);
std::cout<<r<<'\n';
std::cin>>r;
return 0;
}
对compare模版定义了 const &int的特化,请预测结果是:
?
实际上结果是
-1
-1
-1
1
也就是四个调用都实例了函数模版,并没有调用特化模版,甚至常量引用third1,third2作为参数仍然么有调用对应的特化模版。
如果我们去掉特化模版形参的const和&如下:
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
template<>
int compare( int ls, int rs)
{
std::cout<<"first \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int first1(1),first2(2);
int &second1(first1);
int &second2(first2);
const int &third1(first1);
const int &third2(first2);
int r(0);
r = compare(first1,first2);
std::cout<<r<<'\n';
r = compare(second1,second2);
std::cout<<r<<'\n';
r = compare(third1,third2);
std::cout<<r<<'\n';
r = compare(3,2);
std::cout<<r<<'\n';
std::cin>>r;
return 0;
}
结果为
first
-1
first
-1
first
-1
first
1
全部调用特化函数模版。
当特化模版形参为引用时,如下
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
template<>
int compare( int &ls, int &rs)
{
std::cout<<"first \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int first1(1),first2(2);
int &second1(first1);
int &second2(first2);
const int &third1(first1);
const int &third2(first2);
int r(0);
r = compare(first1,first2);
std::cout<<r<<'\n';
r = compare(second1,second2);
std::cout<<r<<'\n';
r = compare(third1,third2);
std::cout<<r<<'\n';
r = compare(3,2);
std::cout<<r<<'\n';
std::cin>>r;
return 0;
}
结果是
-1
-1
-1
1
这次所有都调用的是实例化的函数模版而不是特化函数模版。2.函数模版的参数变化
接下来对函数模版compare添加引用
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T &ls, T &rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
template<>
int compare(const int& ls,const int& rs)
{
std::cout<<"first \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int first1(1),first2(2);
int &second1(first1);
int &second2(first2);
const int &third1(first1);
const int &third2(first2);
int r(0);
r = compare(first1,first2);
std::cout<<r<<'\n';
r = compare(second1,second2);
std::cout<<r<<'\n';
r = compare(third1,third2);
std::cout<<r<<'\n';
r = compare(3,2);
std::cout<<r<<'\n';
std::cin>>r;
return 0;
}
调用
r = compare(3,2);
时提示
1>e:\sourcecodes\comparetest\comparetest\comparetest.cpp(67) : error C2664: 'compare' : cannot convert parameter 1 from 'int' to 'int &'
这个错误和
int &a = 1;
这样的代码语句错误是一样的。
以下转自http://developer.51cto.com/art/201002/183476.htm
关于引用的初始化有两点值得注意:
(1)当初始化值是一个左值(可以取得地址)时,没有任何问题;
(2)当初始化值不是一个左值时,则只能对一个const T&(常量引用)赋值。而且这个赋值是有一个过程的:
首先将值隐式转换到类型T,然后将这个转换结果存放在一个临时对象里,最后用这个临时对象来初始化这个引用变量。
- const double& cdr = 1; // ok
- double temp = double(1);
- const double& cdr = temp;
注释掉语句
r = compare(3,2);
std::cout<<r<<'\n';
所得结果为
-1
-1
-1
所以我们再次将函数模版compare的形参加上const
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( const T &ls, const T &rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
template<>
int compare(const int& ls,const int& rs)
{
std::cout<<"first \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int first1(1),first2(2);
int &second1(first1);
int &second2(first2);
const int &third1(first1);
const int &third2(first2);
int r(0);
r = compare(first1,first2);
std::cout<<r<<'\n';
r = compare(second1,second2);
std::cout<<r<<'\n';
r = compare(third1,third2);
std::cout<<r<<'\n';
r = compare(3,2);
std::cout<<r<<'\n';
std::cin>>r;
return 0;
}
结果为
first
-1
first
-1
first
-1
first
1
这次均调用了特化的函数模版!!!!
3.加上重载函数
接下来我们在特化模版后再加入同样形参的函数
int compare(const int& ls,const int& rs)
如下
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( const T &ls, const T &rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
template<>
int compare(const int& ls,const int& rs)
{
std::cout<<"first \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare(const int& ls,const int& rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int first1(1),first2(2);
int &second1(first1);
int &second2(first2);
const int &third1(first1);
const int &third2(first2);
int r(0);
r = compare(first1,first2);
std::cout<<r<<'\n';
r = compare(second1,second2);
std::cout<<r<<'\n';
r = compare(third1,third2);
std::cout<<r<<'\n';
r = compare(3,2);
std::cout<<r<<'\n';
std::cin>>r;
return 0;
}
这次结果为
SECOND
-1
SECOND
-1
SECOND
-1
SECOND1
从结果我们可以看出函数重载了函数模版以及特化模版。
4重载和函数模版
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare(const int& ls,const int& rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
结果
SECOND
-1
SECOND
-1
SECOND
-1
SECOND
1
重载函数去掉const,只留&
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare( int& ls, int& rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
结果为
SECOND
-1
SECOND
-1
-1
1
说明int,int &调用的函数,const &,常量数字调用的函数模版。
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare( int ls, int rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
结果
SECOND
-1
SECOND
-1
SECOND
-1
SECOND
1
均调用的函数非模版。
为模版添加引用
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T &ls, T &rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare( int ls, int rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
结果
SECOND
-1
SECOND
-1
SECOND
-1
SECOND
1
再添加常量
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( const T &ls, const T &rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare( int ls, int rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
结果
SECOND
-1
SECOND
-1
SECOND
-1
SECOND
1
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T &ls, T &rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare( int &ls, int &rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
结果
SECOND
-1
SECOND
-1
r = compare(3,2);
出错
1>e:\sourcecodes\comparetest\comparetest\comparetest.cpp(78) : error C2665: 'compare' : none of the 2 overloads could convert all the argument types
1> e:\sourcecodes\comparetest\comparetest\comparetest.cpp(9): could be 'int compare<int>(T &,T &)'
1> e:\sourcecodes\comparetest\comparetest\comparetest.cpp(33): or 'int compare(int &,int &)'
#include "stdafx.h"
#include<iostream>
#include<ostream>
#include<istream>
template<class T>
int compare( T ls, T rs)
{
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
int compare( int &ls, int &rs)
{
std::cout<<"SECOND \n";
if(ls<rs)
return -1;
if(rs<ls)
return 1;
return 0;
}
SECOND
-1
SECOND
-1
-1
最后留下的疑问是当函数模版的参数不是引用时,如下,
int compare( T ls, T rs)
为什么特化模版
template<>
int compare(const int& ls,const int& rs)
没有起到作用
而
template<>
int compare( int ls, int rs)