为什么不重载/命名空间/模板相关的C ++代码编译? [英] Why doesn't this overloading/namespace/template-related C++ code compile?

查看:169
本文介绍了为什么不重载/命名空间/模板相关的C ++代码编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是一些C ++代码:

Here is some C++ code:

namespace A {

int f(int x) { return 0; }
int f(long x) { return 1; }

template<class T> int g(T x) {
  return f(x);
}

}

namespace B {
struct C {};
}

namespace A {
int f(B::C x) { return 2; }
}

void h() {
  A::g(B::C());
}

在命名空间A中,代码声明了函数f的一些重载,一个模板函数g调用f。然后我们在命名空间B中声明一个新类型,并为命名空间A中的新类型重载f。使用g ++ 4.2编译,得到

In namespace A, the code declares a few overloads of a function f, and a templated function g which calls f. Then we declare a new type in namespace B and overload f for the new type in namespace A. Compiling with g++ 4.2 gives

order.cpp: In function ‘int A::g(T) [with T = B::C]’:
order.cpp:21:   instantiated from here
order.cpp:7: error: no matching function for call to ‘f(B::C&)’
order.cpp:3: note: candidates are: int A::f(int)
order.cpp:4: note:                 int A::f(long int)

如果我执行以下任何操作,代码就可以正常工作:

The code works if I do any of the following:


    <
  1. 将B :: C的f重载到命名空间B中(感谢Koenig查询)。

  2. 移动

我特别困惑于(3) ,因为我的印象是重载决议应该独立于声明的顺序。这是预期的C ++行为吗?

I'm particularly puzzled by (3), since I was under the impression that overload resolution should be independent of the order of declarations. Is this expected C++ behavior?

推荐答案

Clang给出以下错误消息,

Clang gives the following error message, which gives some clues to the problem:

$ clang -fsyntax-only test.cc -Wall
test.cc:7:10: error: call to function 'f' that is neither visible in the
      template definition nor found by argument-dependent lookup
  return f(x);
         ^
test.cc:21:3: note: in instantiation of function template specialization
      'A::g<B::C>' requested here
  A::g(B::C());
  ^
test.cc:17:5: note: 'f' should be declared prior to the call site or in
      namespace 'B'
int f(B::C x) { return 2; }
    ^
1 error generated.

具体来说,您已经遇到模板定义中依赖名称的两阶段查找的详细信息。在C ++ 98中,[temp.dep.candidate]说:

Specifically, you've run into a detail of two-phase lookup of dependent names in template definitions. In C++98, [temp.dep.candidate] says:


对于依赖于模板参数的函数调用,函数名是一个非限定id而不是一个模板id,使用通常的查找规则(3.4.1,3.4.2)找到候选函数,除了:

For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:


  • 对于使用非限定名称查找(3.4.1)的查找部分,只能找到具有模板定义上下文外部链接的函数声明。

  • 使用关联名称空间(3.4.2)的查找部分,只找到在模板定义上下文或模板实例化上下文中找到的外部链接的函数声明。

由于使用关联的命名空间找不到 A :: f(B :: C x)参数相关的查找),它必须在模板定义站点可见,而不只是在实例化点。

Since A::f(B::C x) isn't found using associated namespaces (i.e. argument-dependent lookup), it has to be visible at the template definition site, not just at the point of instantiation.

这篇关于为什么不重载/命名空间/模板相关的C ++代码编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆