请教一个模板重载的问题

Bureaucratist 2007-12-06 08:58:40
使用vs.net 2003编写C++。

定义了一个模板
template <class T>
T function(T , T);


还定义有一个结构
struct sa;


使用template specilization 如下
template <> sa& function<sa&>(sa& , sa& );

编译器通知我错误。

可是我如下定义模板

定义了一个模板
template <class T>
T& function(T& , T&);


还定义有一个结构
 struct sa;


使用template specilization 如下
template <> sa& function<sa>(sa& , sa& );

便不会出错,能顺利编译执行。

不解,请教,非常感谢,就这点儿分了,还请见谅。OTL
...全文
172 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
fish6344 2007-12-09
  • 打赏
  • 举报
回复
不好意思,更正" 然而上述程序在BC6.0及Gcc上则没有问题。所以,这不是你的程序错误,而是编译器的个性问题。"为

然而上述程序在BC6.0及上则没有问题。所以,这不是你的程序错误,而是编译器的个性问题。

上述所谓VC7.1的'怪癖',原来不只独有,Dve_C++4也是如此,但很多关于模板技术的资料包括《C++ Templage The complete Guaid》等都没有讨论这个问题!BC6.1没有此问题,我认为,从'完全特化'的语意看,应是BC6.0是对此语意堪称完美的支持!
kangyidadi 2007-12-07
  • 打赏
  • 举报
回复
template <> sa& function<sa&>(sa& , sa& );
在VC6.0下无任何错误。
fish6344 2007-12-07
  • 打赏
  • 举报
回复
你的程序:
//定义了一个模板
template <class T>
T function(T , T);

struct sa;

template <> sa& function<sa&>(sa& , sa& );//外层修饰符和主模板不一致,编译期错误!

原因是这样:首先,这不是模板函数重载的问题,而是函数模板特化的问题!对此,VC7.1有一个'怪癖',它要求完全特化的模板函数其模板实参的外层修饰符('const'、'&'等)必须和主模板一致!否则生成编译期错误,类似" 'function<sa&>(sa& , sa& )' 不是模板特化..."。因而面对如下程序:

template <class T>
T& function(T& , T&);

struct sa;

template <> sa& function<sa>(sa& , sa& );//Ok!外层修饰符和主模板一致!

便不会出错,能顺利编译执行。

然而上述程序在BC6.0及Gcc上则没有问题。所以,这不是你的程序错误,而是编译器的个性问题。


Bureaucratist 2007-12-07
  • 打赏
  • 举报
回复
今天彻底明白了,实际上是我的程序中的function(x, y) 引用方式错了,

因为使用sa& 替换 T进行模板具体化,所以function(x, y)只会使用Generic-Template,
而function(x& , y& )才是使用具体化的模板,当然还是使用引用传递参数。

非常感谢大家的关注。
WeinJones 2007-12-06
  • 打赏
  • 举报
回复
晕,你没弄清楚模版函数的真正作用吧?怎么这么定义?


// CPP_t.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

template <class T>
T function(T , T);

struct sa
{
string s;
int value;
};

template <> sa& function<sa&>(sa& , sa& ); //??????????

int _tmain(int argc, _TCHAR* argv[])
{
sa x, y;
x.s = "X";
x.value = 3;
y.s = "Y";
y.s = 98;
//cout << function(10, 15) << endl; //模版并非如此“万能”
cout << function(x, y).s << endl; //不会出错了
cin.get();
return 0;
}

template <class T>
T function(const T a,const T b)
{
return (a.value>b.value?a:b); //改成这样,如果不想改,那就必须保证<class T>的类型都重载了">"符。
}

template <> sa& function<sa&>(sa& a, sa& b) //这个是干什么的?万一还有个struct as岂不是又要为as写一个“模版”函数?
{
return (a.value>b.value?a:b);
}
taodm 2007-12-06
  • 打赏
  • 举报
回复
你为什么一定要陷在函数模板特化里?
Bureaucratist 2007-12-06
  • 打赏
  • 举报
回复
baihacker 2007-12-06
  • 打赏
  • 举报
回复
关于函数模板的.....可以看看这篇文章
http://blog.csdn.net/baihacker/archive/2007/11/26/1902179.aspx
baihacker 2007-12-06
  • 打赏
  • 举报
回复
你应该使用重载而不是使用全特化!
template <> sa& function<sa&>(sa& a, sa& b)
{
return (a.value>b.value?a:b);
}
只是一个

function template with T = sa&


cout << function(x, y).s << endl;
检测到x,y的类型是sa
将尝试匹配模板
function template with T = sa
所以你的
function template with T = sa&
没有被调用......错误就明显了

你可以用:
sa function(sa a, sa b)
{
return (a.value>b.value?a:b);
}
也可以用
template <>
sa function<sa>(sa a, sa b)
{
return (a.value>b.value?a:b);
}全特化
前者的优先级高于后者...
再或者用
template <class T>
const T& function(const T& a,const T& b)
{
return (a>b?a:b);
}

template <>
const sa& function(const sa& a,const sa& b) //这是利用类型推测全特化模板...
{
return (a.value>b.value?a:b);
}
Bureaucratist 2007-12-06
  • 打赏
  • 举报
回复
出错的 程序如下:

// CPP_t.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

template <class T>
T function(T , T);

struct sa
{
string s;
int value;
};

template <> sa& function<sa&>(sa& , sa& );

int _tmain(int argc, _TCHAR* argv[])
{
sa x, y;
x.s = "X";
x.value = 3;
y.s = "Y";
y.s = 98;
cout << function(10, 15) << endl;
cout << function(x, y).s << endl;
cin.get();
return 0;
}

template <class T>
T function(T a, T b)
{
return (a>b?a:b);
}

template <> sa& function<sa&>(sa& a, sa& b)
{
return (a.value>b.value?a:b);
}


VS.2005下面也出错了, 请教。
WeinJones 2007-12-06
  • 打赏
  • 举报
回复
前一个版本是因为你传给function的参数和specilize给模版的类型不符吧?

模版定义:
template<class T>
T& funciont(T&,T&);

specilization:
sa& function<sa&>(sa & ,sa &);

这意味着你<class T>的T类型是sa的引用类型。
那么function的两个参数就是sa引用的引用类型(sa &&,sa &&)
而你只把sa的引用做了参数放在了function的定义中(也包括返回值)
就会出问题了。

所以你前面一个版本不改别的,只把function的定义改成如下
sa& function<sa>(sa & ,sa &)
就能正常运行了。

另外如果使用这样的函数名,最好把自己的代码放进一个自定义的名称空间。
避免不必要的错误。
lynnboy 2007-12-06
  • 打赏
  • 举报
回复
我觉得可能是VC7.1的编译器的引用类型有点问题。
G++没报任何错。
taodm 2007-12-06
  • 打赏
  • 举报
回复
1换wxdevpp或者vc2005express再试,VC2003是bug多到不可用的版本。
2函数,优先考虑重载,而不是模板特化
3function也很容易和库里的一些东西重名冲突。
yshuise 2007-12-06
  • 打赏
  • 举报
回复
记忆中函数是不可以特化的
zenny_chen 2007-12-06
  • 打赏
  • 举报
回复
最後に、よく頑張ってね。
zenny_chen 2007-12-06
  • 打赏
  • 举报
回复
如果你这样调用function(&x, &y);
那么这个函数就不是你所特化的template <> sa& function<sa&>(sa& , sa& );
而是被实例化为template<> sa* function<sa*>(sa*, sa*);
因此你在调用是比较的不是两个字符串,而是它们的地址,这样:cout << function(&x, &y)->s << endl;
可以正常输出。

另外,以下代码通过VS2005.NET的编译及运行:


#include <iostream>
#include <string>
using namespace std;

template <class T>
T function(T , T);

struct sa
{
string s;
int value;
int operator > (const sa &b)
{
if(value > b.value)
return 1;
else
return 0;
}
};


template <class T>
T function(T a, T b)
{
return a > b? a:b;
}

template <> sa& function<sa&>(sa& , sa& );

int main(int argc, char* argv[])
{
sa x, y;
x.s = "X";
x.value = 3;
y.s = "Y";
y.value = 98;
cout << function(10, 15) << endl;
cout << function(x, y).s << endl;
return 0;
}
Bureaucratist 2007-12-06
  • 打赏
  • 举报
回复
刚刚试了一下

使用一楼的程序(程序有个小错误,y.s = 98;改为y.value = 98;),function调用结构sa的时候,程序并不会使用显式具体化的函数,而是仍然使用generic template的template <class T> T function(T, T);创建函数实例。

如果我 这样调用 function(&x, &y); 程序工作正常,

可是形参是引用,实参的调用并不用使用地址啊,是不是模板把template <> sa& function(sa& , sa& )中的 sa& 看成 地址的调用,而不是引用,我想这样理解可以理解通顺。

非常感谢几位不辞辛苦的回答,非常感谢。
还蒙高见。

ryfdizuo 2007-12-06
  • 打赏
  • 举报
回复

#include <iostream>
#include <string>
using namespace std;

template <class T>
T const& function(T const&, T const&);

struct sa
{
string s;
int value;
};

template <>
sa const& function(sa const& , sa const& ); //模板特化

int main()
{
sa x, y;
x.s = "X";
x.value = 3;
y.s = "Y";
y.s = 98;
cout << function(10, 15) << endl;
cout << function<sa>(x, y).s << endl;
cout << function<sa>(x, y).s << endl; //这里可以显式的指定类型;
return 0;
}

template <class T>
T const& function(T const& a, T const& b)
{
return (a>b ? a:b);
}
template<>
sa const& function(sa const& a, sa const& b)
{
return (a.value>b.value?a:b);
}
to_ker 2007-12-06
  • 打赏
  • 举报
回复
楼上的:


template <> sa& function<sa&>(sa& a, sa& b) //这个是干什么的?万一还有个struct as岂不是又要为as写一个“模版”函数?
{
return (a.value>b.value?a:b);
}

这是一个模板的特化,在这个模板函数中,对这个特别的类型做特殊处理

可以去看一下STL的源码.这样的用法很常见

65,184

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧