关于模板

zpk1234 2008-03-08 01:42:13
定义一个模板函数,



template< typename T>
int compare(const T& val1, const T& val2 )
{
if( val1 > val2 )
return 1;
else
{
if( val1 == val2 )
{
return 0;
}
else
{
return -1;
}
}
}



可是这个函数对于指针比较的是指针所指向的地址,而不是指针所指向的内容,请问该如何改,才能使的这个函数比较的是指针的内容 ,
请指教
...全文
187 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
fish6344 2008-03-12
  • 打赏
  • 举报
回复
17、18楼朋友的意见是正确的!7楼的程序的确只适合于内建类型,而没能适合用户自定义类型。因为它会强制用户自定义类要有合适的关糸运算符(这当然是类设计者的义务),以及合适的转换函数(这比效麻烦),不这样的话又会有编译期错误(在运用模板的时候,常有这样的情况,语意、程序逻辑都正确,却不能得到编译器的支持),比较之下,可能还是用1楼的第2个建议(第1个是错的),是最佳决策!
fish6344 2008-03-12
  • 打赏
  • 举报
回复
to 20楼:

你的意见很正确,这个看似简单的问题还真是不简单!关于7楼的程序应该说程序逻辑并无问题,但是如不用重新解释操作,则编译器不认账,它在编译初期的语汇分析阶段决不放这一错误:"以一个引用非法的间接寻址...",但重新解释运算仅适用于整型及指针,这一局限开始时被我忽略了。以至于上述程序仅适用于楼主的程序例-即long整型!

实际上,楼主的问题,仅供我们作为研究语言的游戏而已(通过寻找楼主问题的解,可以从一个方面更加了解我们的C++),就问题的实际意义而言,楼主的想法无疑是不妥的。因为,对于函数模板:

template< typename T>int compare(const T& val1, const T& val2 );

它提供的接口表达了一种语意:就是这样一个函数,它接受二个类型指定的参数的引用进行比较,更确切的说,如果T是指针,该函数就应该接受二个指针进行比较运算,而不是这二个指针的提领物的比较运算!如果楼主的愿望得以满足,则compara函数接口语意就有了多义性。就象我们为某一类型重载一个'*'指针提领操作,却又在该操作的内部实现为'&'地址解析或其它什么荒唐的操作(脱逸原接口语意).......
rularys 2008-03-12
  • 打赏
  • 举报
回复
to 19楼:
“7楼的程序的确只适合于内建类型,因为它会强制用户自定义类要有合适的关糸运算符(这当然是类设计者的义务),以及合适的转换函数(这比效麻烦)”

7楼的程序其实也不适合于内建类型,另一方面,就算用户自定义了合适的关系运算符,7楼的程序对于自定义类型也是不会出现预期的效果的——这正是我的意思。我之所以提出这个问题,就是想看看有无解决方法。我觉得7楼的设计更接近面向对象的思想——类型的类型也可以是一个“对象”。


如果7楼的程序转为比较大小,而不是比较等与不等,那么传入int类型的对象就会表现出不一致:
实际上本来有:
0>-1,
但是7楼的程序会判定为:FFFFFFFF(-1)>0

如若不信,请验证。

对于楼主的问题,我觉得楼主是有些牵强了,明明是要比较的某个类型,为何又要强制转换到另一个类型呢?直接传入指针的解引用不就好了么?就是多加一个解引用符号“*”的代价而已,而且程序本身设计为是对参数的引用而不是值拷贝,不会出现值传递的开销,我是这样建议的。其实程序已经做的比较好了,这是我的个人意见。
rularys 2008-03-11
  • 打赏
  • 举报
回复
关键的地方在这里:

T const* _pa = reinterpret_cast <T const*> (val1);
T const* _pb = reinterpret_cast <T const*> (val2);

这两句已经改变了参数的实际类型;实际比较的类型还是指针,虽然把参数(指针)指向的地方取了值。


比如,如果传入的是 int*类型的参数,这两句话会将参数解释为 int**,于是后面的语句比较的是将指针所指向的值
解引用得到一个int*类型的值,而不是实际的int 类型的值。这时候表现的行为还大概一致,因为不管将数值解释为int还是int*,他们之间的关系几乎是一样;如果传入了负数的指针,那么就会出现不一致的行为了。

更可能的是,如果传入的是自定义类型的、重载了关系运算符号的类型对象的指针,那么自定义的关系运算符根本不会得到调用,将出现预期之外的表现
rularys 2008-03-11
  • 打赏
  • 举报
回复
貌似7楼的 T 不支持已经重载了关系运算符的类
IT_lau 2008-03-11
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 fish6344 的回复:]
to 12楼:

当然!对于7楼的程序而言,类模板'template <typename T> class IsPtr'在目标程序中并不会被实例化,因而它的使用只是增加源代码的体积(要多打字),而在目标代码中,几乎没有踪影。其余的代码也是最基本的需求。且T类型是否是指针以及相应的处理代码均在编译时决议,因而有利于代码的执行效率!唯一的缺点是代码不够优美,有点象VB程序员的作品......
[/Quote]
有同感,,,lz 散分啊
fish6344 2008-03-11
  • 打赏
  • 举报
回复
1楼的第一个意思是:"可以用偏特化属性",这显然是行不通的,因为语言暂时还不能支持函数模板的偏特化!

第二个意思是:"或者直接传递*T",例如:

int main()
{
//如下程序段将向屏幕输出"相等"!
long a = 12,b = 12;
long const*_p1 = &a;
long const*_p2 = &b;

compare(*_p1,*_p2) ? cout << "不相等!" : cout << "相等!";
cout << endl;

_PAUSE;
}

这样也可以,只是它苛求使用者使用表达式计算而得实参,而不是直接使用实参。
asewq 2008-03-11
  • 打赏
  • 举报
回复
1楼说得挺对的啊,直接比较(*T)不就行了?
compare(*val1, *val2)
fish6344 2008-03-10
  • 打赏
  • 举报
回复
to 12楼:

当然!对于7楼的程序而言,类模板'template <typename T>class IsPtr'在目标程序中并不会被实例化,因而它的使用只是增加源代码的体积(要多打字),而在目标代码中,几乎没有踪影。其余的代码也是最基本的需求。且T类型是否是指针以及相应的处理代码均在编译时决议,因而有利于代码的执行效率!唯一的缺点是代码不够优美,有点象VB程序员的作品......
IT_lau 2008-03-09
  • 打赏
  • 举报
回复
7楼用的枚举吗 ?
IT_lau 2008-03-09
  • 打赏
  • 举报
回复
要回引用函数啊
hityct1 2008-03-09
  • 打赏
  • 举报
回复
ding
fish6344 2008-03-09
  • 打赏
  • 举报
回复
虽然,肯定可以另写一个函数专用于指针提领值的比较运算,但是,那样的话就是增加了一个函数接口,也即改变了compare函数接口,这不符合楼主的需求。事实上,7楼中的程序巧妙的运用模板技术(当然增加了代码的体积以及额外的类模板),完全可以在编译期决议出,T是指针或是非指针,以用合适的比较代码,实现一个compare接口,以适应某类型及其指针提领值的比较。
terran_ye 2008-03-09
  • 打赏
  • 举报
回复
看过一本书,上面也提到这个问题,书上用的是再写一个比较字符窜的非模板的函数
fish6344 2008-03-09
  • 打赏
  • 举报
回复
要想既保持compare函数的接口(意即不另写一个专门函数),而又要解决这个问题,可能想到的办法就是对该函数模板进行特化,但你不可能对一个函数模板进行局部特化,例如:

template< typename T>
int compare<T*>(const T val1, const T& val2 )//error!语言暂时还不能支持函数模板的局部特化!
{
//......
}

其次,能想到的办法就就是对该函数模板实施重载,如二楼朋友的建议,但这同样是行不通的(因可能有重载解析多义性之故)!即使某一编译器能够通过这一重载,也并不代表这种重载的策略具有可移值性。至少在我的Gcc、VC7.1及BC6.0编译器上不能解决楼主对compare模板的需求。

但是请不要悲观,请看我的如下程序及注释,可以作为楼主问题的解:(就算抛砖引玉吧!)

#include<ZHOUStd.h>
using namespace std;

//增加一个用于约束条件测试的模板: 
template<typename T>//本模板用于肯定T不是一个指针!
class IsPtr
{
public:
enum { Is = false };
};

//为上述模板作一个指针类型的局部特化!(荣幸,语言支持类的局部特化)
template<typename T>//本模板用于肯定T是一个指针!
class IsPtr<T*>
{
public:
enum { Is = true };
};

template<typename T>
int compare(const T& val1, const T& val2 )
{
if(IsPtr<T>::Is)//在楼主的模板中加入约束条件测试!
{
//当T是指针的时候:
//如下重新解释操作用于消除编译期错误:
T const* _pa = reinterpret_cast<T const*>(val1);
T const* _pb = reinterpret_cast<T const*>(val2);
if( *_pa > *_pb ) return 1;
else
{
if(*_pa == *_pb)
{
return 0;
}
else
{
return -1;
}
}
}
else
{
//当T类型不是指针:
if( val1 > val2 ) return 1;
else
{
if(val1 == val2)
{
return 0;
}
else
{
return -1;
}
}
}
}

int main()
{
//如下程序段将向屏幕输出"相等"!
long a = 12,b = 12;
compare(a,b) ? cout << "不相等!" : cout << "相等!";
cout << endl;

compare(&a,&b) ? cout << "不相等!" : cout << "相等!";
cout << endl;

//如下程序段将向屏幕输出"不相等"!
long c = 12,d = 13;
compare(c,d) ? cout << "不相等!" : cout << "相等!";
cout << endl;

compare(&c,&d) ? cout << "不相等!" : cout << "相等!";
cout << endl;

_PAUSE;//一个利于观察的宏!
}

如上注释,该程序在我的VC7.1、BC6.0编译器上行为良好,可以满足楼主的需求!当然会有一些编译期警告!但GCC则没有任何警告,程序行为一如预期!


shwneo 2008-03-08
  • 打赏
  • 举报
回复
这个函数假设在T上定义了“>”和“==”

zpk1234 2008-03-08
  • 打赏
  • 举报
回复
补充一点的是 这个函数同时也可以比较int和float 类型
int val1 = 1, val2 = 2;
cout<<compare(val1, val2)<<endl;
输出-1
吴丁 2008-03-08
  • 打赏
  • 举报
回复
我靠,我刚一刷新就有人回了!
吴丁 2008-03-08
  • 打赏
  • 举报
回复
实在没办法了,就这样吧
#include "stdafx.h"
#include "stdio.h"
#include "string.h"

template< typename T>
int compare(const T *val1, const T *val2 )
{
if( (*val1) > (*val2) )
return 1;
else
{
if( (*val1) == (*val2) )
{
return 0;
}
else
{
return -1;
}
}

}

int main(int argc, char* argv[])
{
char *a="a";
char *b="a";
int c=1;
int d=2;
int e=1;
printf(" compare(c,d) is %s \n", 0==compare(&c,&d) ? "equal":" un equal");
printf(" compare(c,e) is %s \n", 0==compare(&c,&e) ? "equal":" un equal");

printf(" compare(c,d) is %s \n", 0==compare(&c,&d) ? "equal":" un equal");

printf(" compare(a,b) is %s \n", 0==compare(a,b) ? "equal":" un equal");

printf("Hello World!\n");
return 0;
}
hastings 2008-03-08
  • 打赏
  • 举报
回复
template< typename T>
int compare(T* const& val1, T* const& val2 )
{
if( *val1 > *val2 )
return 1;
else
{
if( *val1 == *val2 )
{
return 0;
}
else
{
return -1;
}
}
}
加载更多回复(1)

64,849

社区成员

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

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