模板函数地址

CodePage 2002-10-09 02:12:25
template <class T>
T add (const T &a, const T &b)
{
return (a+b);
}

int addint (const int &a, const int &b)
{
return (a+b);
}

main()
{
char ca, cb, cc;
int ia, ib, ic;
double da, db, dc;
void * ptr;

ca=cb=cc= 0;
ia=ib=ic= 0;
da=db=dc= 0;

cc = add(ca, cb);
ic = add(ia, ib);
dc = add(da, db);

ic = addint(ia, ib);

ptr = addint; //得到addint()的地址,正确!
ptr = add(ia, ib); //错误 1
ptr = add<int>; //错误 2
ptr = add(int, int); //错误 3
}

如何得到add<int>...的地址????
...全文
148 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Last_Dodo 2002-10-11
  • 打赏
  • 举报
回复
我的ANSI C++编译器是Solaris CC 5.2, HP aCC, IBM visualAge。
CodePage 2002-10-10
  • 打赏
  • 举报
回复
问题已经解决!十分感谢 tianxinet(越来越胖的猴子) 和 do_do(do_do) 的指点。

看了反汇编,才解决问题。

pv = (int (*) (int, int))add;
pv = (char (*) (char, char))add;
pv = (float (*) (float, float))add;
pv = (double (*) (double, double))add;

do_do的方案:每个模板函数的每个实例都定义一个类型,虽然可以做强制类型转换,并且运行正确,但类型太多容易引起混淆。
tianxinet的方案:每个模板函数再定义返回指针的一个模板函数,运行也正确。但是通过反汇编察看得到如下代码:
//pv = fp<int>(&add)
push offset add //地址正确
call fp
mov pv, eax
......
//在 fp 函数里,只是简单的
mov eax, fp

我觉得最直观的还应该是 pv=Add<int>; 但总是编译出错:“无法解析函数重载”,do_do 您说的“ANSI C++编译器”是哪个编译器?我听别人说目前还没有完全遵照ANSI C++标准的编译器。

还有问题:别扔砖头,我是真的不懂
我用的是VC++ 7.0,在 typedef 里面不能使用模板,请问这是VC++的限制还是ISO的限制?

btw: 我一直用c,最近在老伴的压迫之下不得已才学c++(她老显耀java怎么怎么样,我争辩说c++最好,可惜只知皮毛,争不过她。于是就萌发了学透c++的念头,一定要让她心服口服。)现在越学越感到c++的博大精深!我前几天刚来CSDN,还希望大家多多指教。
Last_Dodo 2002-10-10
  • 打赏
  • 举报
回复
1。add_t不叫重载虽然这模板产生的代码的名字处理方法很可能和重载一样。
2。对。
CodePage 2002-10-10
  • 打赏
  • 举报
回复
没有在ISO/IEC 14882-1998找到这个问题,在 over.over 里讲了重载函数的地址,还没有找到模版函数地址的章节。

我还有个不明白:

template <class T> T add_t (T a, T b);



char add_o (char, char);
int add_o (int, int);
float add_o (float, float);
double add_o (double, double);

有何区别。

1,add_o当然是重载,很好理解。而add_t是不是也是重载?
2,如果程序中只调用了int add_t (int, int)是不是编译器不产生char add_t (char, char)的代码?而不管是否调用 char add_o (char, char)都产生代码?
anrxhzh 2002-10-10
  • 打赏
  • 举报
回复
目前的C++标准不支持 template typedef。
详情见:GotW #79
http://www.gotw.ca/gotw/079.htm
tianxinet 2002-10-09
  • 打赏
  • 举报
回复
这里需要澄清两个概念:实例化&特化

特化是模板中的特有概念,所谓特化,也就是明确指定模板中的参数类型.而模板函数在特化时就可以得到地址.这一点你可以在上面我给出的代码中验证:
注释掉下面几行,仍然会得到相应的函数地址:
//cc = add(ca, cb);
//ic = add(ia, ib);
//dc = add(da, db);
paul319 2002-10-09
  • 打赏
  • 举报
回复
c++的底层实现是:模板函数并不在定义模板时具现(可以理解为得到存);而是在用到的时候(实力化并调用)才得以具现;所以向上面那样去取模板函数的地址是错误的,因为函数根本没有占用内存!
Last_Dodo 2002-10-09
  • 打赏
  • 举报
回复
昨天没上班没能直接试。今天试了一下,结果是下面的例子在Solaris,HP,IBM(AIX)上都得出正确的结果:

template <class T>
T add(T t1, T t2)
{
return t1+t2;
}

typedef int (*Foo)(int, int);

int main()
{
Foo foo = add;
cerr << foo(1, 2) << endl;
}

然后试了foo=add<int>发现ANSI C++编译器都正确(但之前的C++编译器说语言错,看来我得好好看一下ANSI C++标准了)。谢谢各位!

不过我没有MS上的C++编译器所以无法证实。
tianxinet 2002-10-09
  • 打赏
  • 举报
回复
应该这样获得模板函数地址:

#include <iostream>

using namespace std;

template <class T>
T add (const T &a, const T &b)
{
return (a+b);
}

int addint (const int &a, const int &b)
{
return (a+b);
}


template <class T>
void* fp(T (*pf)(const T &a, const T &b)) //该模板函数用来获得函数add的地址
{
return pf;
}

void main()
{
char ca, cb, cc;
int ia, ib, ic;
double da, db, dc;
void * ptr;

ca=cb=cc= 0;
ia=ib=ic= 0;
da=db=dc= 0;

cc = add(ca, cb);
ptr = fp<char>(&add);
cout<<"char functional pointer is:"<<ptr<<endl;

ic = add(ia, ib);
ptr = fp<int>(&add);
cout<<"int functional pointer is:"<<ptr<<endl;

dc = add(da, db);
ptr = fp<double>(&add);
cout<<"double functional pointer is:"<<ptr<<endl;

ic = addint(ia, ib);
ptr = addint; //得到addint()的地址,正确!
cout<<"addint functional pointer is:"<<ptr<<endl;


}
CodePage 2002-10-09
  • 打赏
  • 举报
回复
但是add<int>,add<double>的地址确实是存在的呀
CodePage 2002-10-09
  • 打赏
  • 举报
回复
还是不行...

kwok_1980 2002-10-09
  • 打赏
  • 举报
回复
"但是add<int>,add<double>的地址确实是存在的呀"

>>这是什么???是class吗?
>>这样写是写在template class里面的template function吧!!?!?
>>没有这样的写法!至少我没有看过!
anrxhzh 2002-10-09
  • 打赏
  • 举报
回复
#include <iostream>
#include <string>

template <class T>
T add (const T &a, const T &b)
{ return (a+b); }

int main()
{
int (*p)(const int&,const int&);
std::string (*p2)(const std::string&,const std::string&);

p = add<int>;
p2 = add<std::string>;

std::cout << p(1,2) << ' ' << p2("hello"," world") << std::endl;
}

//output:
//3 hello world
Last_Dodo 2002-10-09
  • 打赏
  • 举报
回复
ptr = add(ia, ib); //错误 1

这没有语法错但语义错。add(ia, ib)是函数调用,其结果是返回int。用int赋值给void*自然是错误。

ptr = add<int>; //错误 2

这语法错。

ptr = add(int, int); //错误 3

这也是语法错。

你要的可能是:
typedef int (*ptr)(int, int)
...
ptr = add; //编译器应该会instantiate一个int add(int, int)函数然后把它的地址赋值给ptr。如果不行,试先调用add(ia, ib)去强迫编译器instantiate int add(int, int)。然后做ptr=add的赋值。

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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