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的有用答案,不仅指出了标准的相关部分,还提供了替代解决方案.感谢大卫罗德里格斯 – 当我不理解所提议的解决方案和所有其他贡献者时,他的解释.
解决方法
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) {} }