微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 使用限定类型实例化的模板内的函数的名称解析

考虑以下C代码示例:
namespace n
{
    struct A {};
}

struct B {};

void foo(int) {}

template<typename T>
void quux()
{
    foo(T());
}

void foo(n::A) {}
void foo(B) {}


int main()
{
    quux<n::A>(); // Error (but works if you comment out the foo(int) declaration)
    quux<B>();    // Works

    return 0;
}

如注释中所示,模板实例化quux< n :: A>()会导致编译器错误(在GCC 4.6.3上):

foo.cpp: In function ‘void quux() [with T = n::A]’:
foo.cpp:22:16:   instantiated from here
foo.cpp:13:5: error: cannot convert ‘n::A’ to ‘int’ for argument ‘1’ to ‘void foo(int)’

有人可以向我解释发生了什么事吗?我希望它与quux< B>()的工作方式相同.当foo被认为是依赖时,它必须与某些事情有关.不幸的是我的C foo不够好.当foo(int)声明不存在时,该示例编译正常,这对我来说也是令人惊讶的.

任何提示,解释和解决方法都是受欢迎的.

更新1:

我不想(读不了)在quux的定义之前移动foo(n :: A)的声明(这将避免错误).

更新2:

感谢David指出相关问题Template function call confused by function with wrong signature declared before template.Johannes Schaub – litb接受的答案提出了一个包装类解决方案,在我的情况下也可以作为一种解决方法.但是,我并不是百分之百满意.

更新3:

我通过将foo(n :: A)的定义放在命名空间n中解决了这个问题.感谢Jesse Good和bames53的有用答案,不仅指出了标准的相关部分,还提供了替代解决方案.感谢大卫罗德里格斯 – 当我不理解所提议的解决方案和所有其他贡献者时,他的解释.

解决方法

我认为规则是14.6.4.2p1:

For a function call that depends on a template parameter,the
candidate functions are found using the usual lookup rules (3.4.1,
3.4.2,3.4.3) except that:

— For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3),only
function declarations from the template deFinition context are found.

— For the part of the lookup using associated namespaces (3.4.2),only
function declarations found in either the template deFinition context
or the template instantiation context are found.

void foo(n :: A){}在模板定义上下文中不可见,因为它位于后面且foo与n :: A不在同一名称空间中.所以它需要在模板定义之前可见,或者包含在同一名称空间中,如下所示:

namespace n
{
    void foo(n::A) {}
}

原文地址:https://www.jb51.cc/c/118501.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐