模板函数地址
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>...的地址????
问题点数:20、回复次数:14Top
1 楼do_do(do_do)回复于 2002-10-09 03:43:18 得分 10
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的赋值。
Top
2 楼CodePage(代码页)回复于 2002-10-09 04:32:56 得分 0
还是不行...
Top
3 楼CodePage(代码页)回复于 2002-10-09 04:35:10 得分 0
但是add<int>,add<double>的地址确实是存在的呀Top
4 楼tianxinet(越来越胖的猴子)回复于 2002-10-09 11:45:59 得分 0
应该这样获得模板函数地址:
#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;
}Top
5 楼paul319(清风客)回复于 2002-10-09 12:30:01 得分 0
c++的底层实现是:模板函数并不在定义模板时具现(可以理解为得到存);而是在用到的时候(实力化并调用)才得以具现;所以向上面那样去取模板函数的地址是错误的,因为函数根本没有占用内存!Top
6 楼tianxinet(越来越胖的猴子)回复于 2002-10-09 12:38:10 得分 10
这里需要澄清两个概念:实例化&特化
特化是模板中的特有概念,所谓特化,也就是明确指定模板中的参数类型.而模板函数在特化时就可以得到地址.这一点你可以在上面我给出的代码中验证:
注释掉下面几行,仍然会得到相应的函数地址:
//cc = add(ca, cb);
//ic = add(ia, ib);
//dc = add(da, db);
Top
7 楼anrxhzh(百宝箱)回复于 2002-10-09 15:47:55 得分 0
#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 worldTop
8 楼kwok_1980(Mars)回复于 2002-10-09 16:07:46 得分 0
"但是add<int>,add<double>的地址确实是存在的呀"
>>这是什么???是class吗?
>>这样写是写在template class里面的template function吧!!?!?
>>没有这样的写法!至少我没有看过!
Top
9 楼do_do(do_do)回复于 2002-10-09 23:53:52 得分 0
昨天没上班没能直接试。今天试了一下,结果是下面的例子在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++编译器所以无法证实。Top
10 楼CodePage(代码页)回复于 2002-10-10 03:44:35 得分 0
没有在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)都产生代码?
Top
11 楼do_do(do_do)回复于 2002-10-10 07:20:39 得分 0
1。add_t不叫重载虽然这模板产生的代码的名字处理方法很可能和重载一样。
2。对。Top
12 楼CodePage(代码页)回复于 2002-10-10 08:57:15 得分 0
问题已经解决!十分感谢 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,还希望大家多多指教。Top
13 楼anrxhzh(百宝箱)回复于 2002-10-10 13:00:55 得分 0
目前的C++标准不支持 template typedef。
详情见:GotW #79
http://www.gotw.ca/gotw/079.htmTop
14 楼do_do(do_do)回复于 2002-10-11 01:00:41 得分 0
我的ANSI C++编译器是Solaris CC 5.2, HP aCC, IBM visualAge。Top




