当前位置:  开发笔记 > 编程语言 > 正文

哪种编译器适用于以下重载/特化行为?

如何解决《哪种编译器适用于以下重载/特化行为?》经验,为你挑选了1个好方法。

请考虑以下代码:

#include 

namespace Foo {
  template 
  void foo(T *, int) { puts("T"); }

  template 
  struct foo_fun {
    static void fun() { foo((T *)0, 0); };
  };
}

namespace Foo {
  void foo(int *, int) { puts("int"); }
}

using namespace Foo;

int main() {
  foo_fun fun;
  fun.fun();
}

什么是预期产量?"T"还是int?

一个编译器(来自Apple的Xcode 3.1.2的gcc 4.0.1)输出"int",另外两个编译器(gcc 4.1.2和4.1.3)输出"T".

如果我在foo(T*,int)版本之前移动foo(int*,int)声明/定义,则全部输出"int".在这种情况下,当前标准是否定义了重载/特化的顺序?



1> CB Bailey..:

第二个void foo(...是重载(而不是特化),它在定义中不可见,foo_fun::fun因此在模板定义的上下文中找不到它.因为T*是依赖类型,foo所以表达式中的分辨率foo((T*)0, 0)将被延迟,直到模板实例化时间和实例化的上下文也将被考虑.但是,标准的14.6.4.2表示如果函数名称是非限定id但不是模板ID,那么对于非ADL查找,仅考虑在模板定义点可见的函数.Foo命名空间中没有函数参数,因此不会发生参数依赖查找,因此模板版本为foo 被调用而不是非模板重载.

非常感谢对这个答案的修正.

如果您使其成为如下所示的特化,那么在模板实例化时选择特化,只要相关的特化在首次实例化函数模板的位置可见,就可以调用特化int.

namespace Foo {
    template<>
    void foo(int *, int) { puts("int"); }
}

当前标准的第14章,但它不是很可读:)

编辑:如果我必须选择标准中最相关的部分,它可能是14.6 [temp.res]第9段.(稍微缩写)如果名称不依赖于模板参数,则该名称的声明应为在名称出现在模板定义中的点的范围内; 该名称绑定到此时发现的声明,并且此绑定不受在实例化时可见的声明的影响.

编辑,编辑:但您还需要考虑14.6.4.2 [temp.dep.candidate].由于所有的相互依赖性,尝试引用标准是非常困难和危险的,这个答案就是一个例子.

推荐阅读
LEEstarmmmmm
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有