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

标签 c++ templates namespaces overloading name-lookup

考虑以下 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:

我不想(读不能)移动 foo(n::A) 的声明在 quux 的定义之前(这样可以避免错误)。

更新 2:

感谢大卫指出相关问题Template function call confused by function with wrong signature declared before template . Johannes Schaub 接受的答案 - litb 提出了一个包装类解决方案,在我的案例中也可以作为一种解决方法。但是,我并不是 100% 满意。

更新 3:

我通过定义 foo(n::A) 解决了这个问题在命名空间 n .感谢 Jesse Good 和 bames53 的有用回答,他们不仅指出了标准的相关部分,还提供了替代解决方案。感谢 David Rodríguez - dribeas 在我没有正确理解所提出的解决方案和所有其他贡献者时的解释。

最佳答案

我认为规则是 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) {}
}

关于c++ - 使用限定类型实例化的模板内函数的名称解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13316727/

相关文章:

c - 在头文件中声明时无法识别结构

c++ - 找不到时如何消除cmake的find_package警告?

c++ - 基于图 block 的横向卷轴游戏教程?

python - 如果 django 模板有一个渲染错误会在生产中无声地失败,如何使测试用例失败

c++ - 编译器会为 ref 参数实例化一个新的模板函数吗?

c# - 为什么 Resharper 代码清理会在 ascx 文件中添加不必要的导入命名空间?

c++ - Visual C++ 中同名内部类的问题

c++ - Qt - 当一个类中有多个 QTcpSocket 时,如何知道哪个 QTcpSocket 发出了 readRead 信号?

c++ - 生成 C++ 在 Atom 中包含 header 保护?

c++ - 构建模板类型的编译时列表?