LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
123
返回列表 发新帖
楼主: realtang

晕倒,VC++不支持C99规范

[复制链接]
发表于 2008-1-6 23:39:59 | 显示全部楼层
Post by hong8292;1803613
引用:
作者:manphiz
2、错误的模板实例化点:
代码:
template<class T> void foo(T a);
template<> void foo<int>(int a);
void bar()
{
    foo('a');
}
template<> void foo<char>(char a);
int main()
{
    bar();  // foo()应该调用foo<int>,实际调用foo<char>
}

// ...
不好意思,我认为你这个例子自身就有问题。
首先,特化template<> void foo<char>(char a)申明在调用之后,而函数bar()调用在之前,而编译器会尝试在bar()调用foo时用<char>实例化template<class T> void foo(T a),所以编译器会报错:该特化申明点错误。所以我认为上面的代码不能通过编译,无论是vc2005或者g++都是这个结果。

尝试稍作改动的下面的例子:
template<class T> void foo(T a)
{
        std::cout<<"template<T>: foo";
        std::cout<<"<"
                      <<typeid(T).name()
                      <<">"
                      <<std::endl;
}
template<> void foo<int>(int a)
{
        std::cout<<"template<>: "
                       <<"foo<int>"<<std::endl;
}
void bar()
{
    foo('a');
}
int main()
{
    bar();
}
如果按照你说的现在没有了template<> void foo<char>(char a), 自然应该调用template<> void foo<int>(int a)了,而实际上编译器还是用<char>实例化基础模版得到
template void foo<char>(char), 并调用之。模板实参的推演是精确匹配的过程,而'a'默认是char型的。
这是在下的拙见,不对之处请指出。

确实,那个例子是错误的,当时没想清楚。多谢指正!
这个例子比较能说明问题(来自 msdn: http://msdn2.microsoft.com/en-us/library/w98s4hs8(VS.80).aspx):
  1. #include <stdio.h>
  2. namespace N {
  3.   void f(int) { printf("f(int)\n");}
  4. }
  5. void g() {
  6.   N::f('a');   // VC++: 应该调用 f(int),实际调用 f(char) 。 g++ 的行为是正确的。
  7. }
  8. namespace N {
  9.   void f(char) { printf("f(char)\n");}
  10. }
  11. int main() {
  12.   g();
  13. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2008-1-10 05:05:31 | 显示全部楼层
回复:manphiz
不会吧~~
我都在2个编译器都试过了,结果都是f(int)...

我个人观点是vs2005虽然不算很好,但不至于这么垃圾吧~_~
回复 支持 反对

使用道具 举报

发表于 2008-1-10 09:37:22 | 显示全部楼层
Post by hong8292;1805013
回复:manphiz
不会吧~~
我都在2个编译器都试过了,结果都是f(int)...

我个人观点是vs2005虽然不算很好,但不至于这么垃圾吧~_~

http://msdn2.microsoft.com/en-us/library/w98s4hs8.aspx
这是 MSDN 自己记录的不符合规范的行为。或许我修改的程序有问题吧(我总是断章取义)?试试这个原始的示例程序吧:
  1. // DependentNames.cpp
  2. #include <stdio.h>
  3. namespace N {
  4.    void f(int) { printf("f(int)\n");}
  5. }
  6. template <class T> void g(T) {
  7.    N::f('a');   // calls f(char) should call f(int)
  8. }
  9. namespace N {
  10.    void f(char) { printf_s("f(char)\n");}
  11. }
  12. int main() {
  13.    g('c');
  14. }
复制代码
另外,这样只是就事论事,并非通过这一个程序来说明 VC 垃圾。目前也没有完全符合标准的编译器。而且标准也并非唯一的评判标准,比如还有性能和实现方法。
回复 支持 反对

使用道具 举报

发表于 2008-1-10 22:28:38 | 显示全部楼层
回复:manphiz

呵呵,我喜欢就事论事~~

对了,关于这里例子我认为是这样的:
对于函数模版,他的实例化点在调用函数的后面,在这个例子中,就是在main的“}”之后。
所以此时f(char) 对于template <class T> void g(T)是可见的,所以它仍然会调用f(char)而不是f(int)。我在GCC下也是这个结果,你试过了吗?~_~
回复 支持 反对

使用道具 举报

发表于 2008-1-11 18:45:58 | 显示全部楼层
Post by hong8292;1805391
对于函数模版,他的实例化点在调用函数的后面,在这个例子中,就是在main的“}”之后。
所以此时f(char) 对于template <class T> void g(T)是可见的,所以它仍然会调用f(char)而不是f(int)。我在GCC下也是这个结果,你试过了吗?~_~

我试过了, gcc 调用的是 f(int) , vc 调用的是 f(char) 。

这其实没什么可讨论的。这是 C++ 标准的规定。基于 C++ 的 name lookup 规则, g() 定义时, f(char) 对其是不可见的。
我的理解:这样做是为了保证不会因为在程序的其他位置添加新的 f() 重载而导致原有程序的行为改变。
回复 支持 反对

使用道具 举报

发表于 2008-1-25 19:41:24 | 显示全部楼层
有图有真相
回复 支持 反对

使用道具 举报

发表于 2008-1-26 09:48:30 | 显示全部楼层
楼上貌似并没有看完所有的讨论吧。
回复 支持 反对

使用道具 举报

发表于 2008-1-28 21:43:01 | 显示全部楼层
vc不是弱,是想搞垄断
所以很多东西都要特殊化,
自创一套,排斥国际标准
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表