【问题标题】:Forward declaring a function in a namespace inside another function in that namespace在该命名空间中的另一个函数内转发声明该命名空间中的函数
【发布时间】:2016-01-01 20:20:44
【问题描述】:

我有两个源文件,a.cppb.cpp。在a.cpp,我有一个函数,foo

namespace ns { void foo() { std::cout << "foo!"; } }

b.cpp 中,我在命名空间ns 中有另一个函数,我想在其中创建原型并调用foo

namespace ns
{

void bar()
{
    void foo();
    foo();       
}

}

虽然以上在语法上是有效的,但它会导致编译器认为foo 位于全局命名空间中(或者至少这是我从执行此操作时得到的链接器错误推断出来的)。我要解决的前两个想法是void ns::foo();namespace ns { void foo(); },但都无效。是否可以在bar 中正确地对该函数进行原型设计?

请注意,我知道我可以简单地将其移至文件范围或头文件,对此有很多问题,但我想专门在另一个函数中对其进行原型设计。我的编译器是最新更新的 MSVC 14.0。

编辑:根据我所做的一些测试以及我们在 cmets 中的讨论,我相信这是一个 MSVC 错误。比较:

namespace ns
{

void bar()
{
    void foo();   // link error, MSVC assumes global namespace
    foo();
}

void foo() { }

} // namespace ns

如前所述,此操作失败。但是,将原型移出函数会使 MSVC 正确地将原型函数放置在封闭的命名空间中:

namespace ns
{

void foo();   // all fine
void bar()
{
    foo();
}

void foo() { }

} // namespace ns

【问题讨论】:

  • @JoachimPileborg 在函数内部无效。 cpp.sh/3g3hu
  • 以下编译运行良好;这不是你想要的吗? gist.github.com/jncornett/8e4d85e6008087438cf5
  • @JoelCornett 它编译得很好,但没有链接,至少不适合我(MSVC 14.0)。
  • @szczurcio 看起来像一个 MSVC 错误。在 gcc 和 clang 上尝试过,它可以工作(Joel Cornett 的 gist.github.com/jncornett/8e4d85e6008087438cf5
  • 标准非常明确:“当一个具有链接的实体的块范围声明未找到引用其他声明时,则该实体是最内层封闭命名空间的成员。但是,这样的声明不会在其命名空间范围内引入成员名称。” [basic.link]p7

标签: c++ visual-c++ namespaces function-prototypes


【解决方案1】:

标准明确了这一点:

3.3.2/11: (..) 块范围内的函数声明和块范围内带有 extern 说明符的变量声明参考 声明是封闭命名空间的成员 (...)

因此:

void bar()
{
    void foo();   // should refer to ns::foo() according to 3.3.2/11
    foo();
}

并且链接应该引用具有相同签名的单独编译的函数:

1.3.17 签名: &lt;function&gt; 名称、参数类型列表和封闭的命名空间(如果有) [注意:签名用作 名称修改和链接。-结束注释]

【讨论】:

  • 这就是我的想法,这就是为什么我将这种行为归咎于 MSVC。 +1 标准参考。
猜你喜欢
  • 2017-05-31
  • 2012-12-18
  • 2017-10-24
  • 2014-08-06
  • 1970-01-01
  • 2017-01-26
  • 2021-11-10
  • 2013-05-19
相关资源
最近更新 更多