模板函数和特化的模板函数以及普通函数

wang37921 2010-04-02 07:06:46
特化的模板函数和普通函数为什么不会重定义?
试了下~好像不会~代码如下~
还有调用顺序~为什么会优先调用普通的函数啊~
那这样写个特化和直接定义一个普通函数有啥区别?调用时实参不会隐式转换?



#include <iostream>
#include <string>



template<typename T>
void Foo(const T& e)
{
std::cout << "The input var type size:" << sizeof(T) <<std::endl
<< "The var value:" << e << std::endl;
}

void Foo(const int& e)
{
std::cout << "The input var type size:" << sizeof(int) <<std::endl
<< "The var value:" << e << std::endl;
}

template<>
void Foo<int>(const int& e)
{
std::cout << "The input var type size:" << sizeof(int) <<std::endl
<< "The var value:" << e << std::endl;
}


int main()
{
int a(12);
std::string b("wang");
Foo(a);
Foo(b);
}

...全文
371 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
晨星 2010-04-04
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 wang37921 的回复:]
所以上面我说懂不懂的界限很模糊~懂其实就是找个能让骗的自己相信的理由~呵呵~不过星哥细讲的还是很有帮助的~
[/Quote]
嘿嘿,也不是骗了。:P
我的意思是,自己心里明白就OK了。至于书上说“重载是指相同的函数名不同的参数列表”,这个没必要说它不对,但同时也不要把它当成严格定义就OK。
wang37921 2010-04-03
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wang37921 的回复:]
谢谢星哥~印象深点了~其实懂不懂的界限也很模糊~呵呵~谢谢星哥的不厌其烦~有问题希望还能看到星哥的回帖~
[/Quote]
所以上面我说懂不懂的界限很模糊~懂其实就是找个能让骗的自己相信的理由~呵呵~不过星哥细讲的还是很有帮助的~

可以理解成一个是void Foo<int>(int);另一个是void Foo(int)。
那只是个语法糖而已
“重载”是指函数名相同,参数列表不同,同时函数模板也会参与到重载解决的过程中。

这些是关键,应该足够骗过自己了~
不过下面的代码让我爽了。。。终于平衡了~代码是错的不过~不过错的很爽~哇哈哈哈~
error C2908: 显式专用化;已实例化“void Foo<int>(const T &)”

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



template<typename T>
void Foo(const T& e)
{
std::cout << "The input var type size:" << sizeof(T) <<std::endl
<< "The var value:" << e << std::endl;
}



int main()
{
int a(12);
Foo(a);
}

template<>
void Foo<int>(const int& e)
{
std::cout << "The input var type size:" << sizeof(int) <<std::endl
<< "The var value:" << e << std::endl;
}

晨星 2010-04-02
  • 打赏
  • 举报
回复
楼主朋友差不多就行了,毕竟又不是要去写编译器,嘿嘿。
其实工程技术领域的“定义”,往往经不起像逻辑学那样的推理的。
反正就是那么回事,大体上,“重载”是指函数名相同,参数列表不同,同时函数模板也会参与到重载解决的过程中——知道这一切就OK了,未必非要总结成一句能将它们全部表达精确的严格定义。
晨星 2010-04-02
  • 打赏
  • 举报
回复
是啊,就是加入到候选集合了,然后编译器从其中挑一个跟调用时所用的实参最匹配的。
C++标准就是C++语言的国际标准(International Standard)规格说明嘛:ISO/IEC 14882 (2003)。
herman~~ 2010-04-02
  • 打赏
  • 举报
回复
呵呵 老大的解释很详细,顶一个
wang37921 2010-04-02
  • 打赏
  • 举报
回复
C++标准
什么东西?
wang37921 2010-04-02
  • 打赏
  • 举报
回复
可以理解成一个是void Foo<int>(int);另一个是void Foo(int)。
那只是个语法糖而已


经典~呵呵~这个应该就是关键吧~
In such a case, the candidate functions generated from each function template are combined with the set of non-template candidate functions.
结合?何解?
加入到这个集合了?
晨星 2010-04-02
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wang37921 的回复:]
我就以为他是将这个类型像宏替换似的,编出一个这样的函数(就像是我们自己编写的普通函数一样)~所以这个时候我就担心会不会和自身的编写的函数产生重定义~
[/Quote]
哦,不是这样的。
宏是由预编译器处理。宏代换发生在编译之前。
而模板却是跟一般的函数一样,一切都由编译器依据各种语法规则来处理。
编译器只有当确定需要使用一个模板实例的时候,才会最终把它生成出来。
而且即使生成出来,也不会形成重定义。可以理解成一个是void Foo<int>(int);另一个是void Foo(int)。
至于调用函数模板时,模板参数可以不写,而让编译器直接推导,那只是个语法糖而已。假如果真推导出来的是它,那最终调用还是void Foo<int>(int)。
wang37921 2010-04-02
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 steedhorse 的回复:]
(2)在后面的13.3.1 Candidate functions and argument lists,一节的第7条又提到:
7 In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction (14.8.3, 14.8.2). Those candidates are then handled as candidate functions in the usual way.113) A given name can refer to one or more function templates and also to a set of overloaded non-template functions. In such a case, the candidate functions generated from each function template are combined with the set of non-template candidate functions.
[/Quote]
感觉这个比较有用~但是看不太明白~英语不过关吧~问题来源自看书的时候他说 模板函数的实例化
我就以为他是将这个类型像宏替换似的,编出一个这样的函数(就像是我们自己编写的普通函数一样)~所以这个时候我就担心会不会和自身的编写的函数产生重定义~
zht_304 2010-04-02
  • 打赏
  • 举报
回复
学习了。
晨星 2010-04-02
  • 打赏
  • 举报
回复
又帮你查了下C++标准。发现了两点:
(1)所谓的“函数名相同,参数列表不同叫做重载”——这只是一般教材里通俗的讲法。也不能算错,只是考虑到模板时,这话也很难说得特别精确,所以大家也就那样说了。C++标准上说的是:
13 Overloading [over]
1 When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded. By extension, two declarations in the same scope that declare the same name but with different types are called overloaded declarations. Only function declarations can be overloaded; object and type declarations cannot be overloaded.

(2)在后面的13.3.1 Candidate functions and argument lists,一节的第7条又提到:
7 In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction (14.8.3, 14.8.2). Those candidates are then handled as candidate functions in the usual way.113) A given name can refer to one or more function templates and also to a set of overloaded non-template functions. In such a case, the candidate functions generated from each function template are combined with the set of non-template candidate functions.
wang37921 2010-04-02
  • 打赏
  • 举报
回复
谢谢星哥~印象深点了~其实懂不懂的界限也很模糊~呵呵~谢谢星哥的不厌其烦~有问题希望还能看到星哥的回帖~
晨星 2010-04-02
  • 打赏
  • 举报
回复
或者这么说:因为函数模板的模板参数可以自动推导,所以模板也是参与函数调用的重载解决过程的。
如果不准自动推导,必需像类模板那样明确写出,那也就不存在这些问题了。
晨星 2010-04-02
  • 打赏
  • 举报
回复
模板跟普通函数也算重载。
wang37921 2010-04-02
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 steedhorse 的回复:]
我记得是这样的:显式特化的模板函数不参与重载解决的过程,只有当最终某个函数模板被选中之后,编译器才会去看该模板有没有相应的显式特化符合所需的参数代换要求。如果有,就使用该显式特化版本,否则编译器自己根据原始模板隐式地实例化一个。
所以,在你的程序中,当参数类型为int时,与一般函数void Foo(const int& e)进行竞争的只有原始模板template<typename T> ……
[/Quote]
具体的计算机执行过程还是不了解~还是谢谢晨星了~
对了~

void Foo(const int& e);
template<typename T> void Foo(const T& e);

这个算是重载吗?重载的定义不是函数形参表不同吗?
晨星 2010-04-02
  • 打赏
  • 举报
回复
我记得是这样的:显式特化的模板函数不参与重载解决的过程,只有当最终某个函数模板被选中之后,编译器才会去看该模板有没有相应的显式特化符合所需的参数代换要求。如果有,就使用该显式特化版本,否则编译器自己根据原始模板隐式地实例化一个。
所以,在你的程序中,当参数类型为int时,与一般函数void Foo(const int& e)进行竞争的只有原始模板template<typename T> void Foo(const T& e)。当参数为int时,根据语言规则,模板自然争不过一般函数,于是该模板的那个显式特化也就根本得不到被考虑的机会。
yanran_hill 2010-04-02
  • 打赏
  • 举报
回复
如果编译器发现一个函数和一个特化函数具有同样好的参数匹配,就优先选用函数
wang37921 2010-04-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 steedhorse 的回复:]
可以形成重载,不会形成重定义。
当函数模板的某种实例化跟某个非模板函数都可以“同样好”地匹配一处函数调用时,优先选择一般函数。
这些是语言规定的。
更详细的规则可以参与《C++ Template》,或者直接看C++语言标准。
[/Quote]

谢谢星哥的关注~但是还是有点疑问~就是“形成重载”这句话~
上面代码中特化的Foo和普通函数~这是一样样的啊~而且模板不是说有实例化的过程嘛~其实就是去生成一个函数的~麻烦星哥能详细的说下~

template<>
void Foo<int>(const int& e);

void Foo(const int& e);
晨星 2010-04-02
  • 打赏
  • 举报
回复
可以形成重载,不会形成重定义。
当函数模板的某种实例化跟某个非模板函数都可以“同样好”地匹配一处函数调用时,优先选择一般函数。
这些是语言规定的。
更详细的规则可以参与《C++ Template》,或者直接看C++语言标准。

65,180

社区成员

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

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