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