从一个命名空间内部调用几个命名空间中重载的函数

7
我有以下代码片段:

我有以下代码片段:

void foo(double a) {}

namespace bar_space
{
  struct Bar {};

  void foo(Bar a) {}
}

foo(double)是一个库中的通用函数。 我有自己的命名空间bar_space和自己的结构体Bar。我想为Bar实现对foo()的重载,从而使Bar更类似于内置类型。

问题出现在当我试图从命名空间内部调用原始的foo(double)时:

namespace bar_space
{
  void baz()
  {
    foo(5.0); // error: conversion from ‘double’ to non-scalar type ‘ssc::bar_space::Bar’ requested
  }
}

这段代码在我的Fedora和Mac上使用gcc编译失败。
调用
foo(5.0)

从命名空间外部或使用
namespace bar_space
{
  ::foo(5.0)
}

这个工作正常,但这并没有使我的新函数像我希望的那样好(其他开发人员也在bar_space内工作)。

bar_space是否隐藏了原始函数?有没有办法使foo(5.0)可以从bar_space内部调用而不需要显式范围解析符(::)?任何帮助都将不胜感激。


1
我是C++的新手,但是你能否使用类似于using bar_space::foo;这样的东西? - dreamlax
这将有助于在bar_space之外使用foo(Bar),但无法将foo(double)引入bar_space。 - Christian Askeland
类似的东西是可能的:http://codepad.org/0IcNXZb6 - DaVinci
3个回答

9
在C++中,有一个叫做名字隐藏的概念。基本上,如果在嵌套作用域中存在一个同名的函数/类,则该函数或类名称将被“隐藏”。这会防止编译器“看到”隐藏的名称。
C++标准的第3.3.7节如下所述:

通过在嵌套的声明区域或派生类(10.2)中显式声明相同的名称可以隐藏名称。

因此,回答您的问题:在您的示例中,void foo(double a);void bar_space::foo(Bar a);“隐藏”。因此,您需要使用::作用域运算符来调用外部函数。

1
没有bar_space::foo(double)。 - DaVinci
1
标准已经明确了,谢谢澄清。 - Christian Askeland
这里缺少的一部分是,在进行名称隐藏之后才应用名称重整。如果反过来,那么代码将按照(错误的)预期工作。 - breakpoint

3
然而,在你的示例代码中,你可以使用类似这样的东西。
namespace bar_space 
{
    using ::foo;
    void baz()
    {
       Bar bar;
       foo(5.0);
       foo(bar);
    }
}

我本来要发布这个答案,只是测试了一下,对我来说编译得很好。(我也被工作中的会议等事情分心了) - CashCow

1

是的,bar_space 隐藏了原始函数,不,你不能使 foo(5.0) 在没有显式作用域的情况下从 bar_space 中调用,如果 foo(double) 在全局命名空间中定义。


好的,我会使用::。虽然我没有提到,但foo()实际上是从math.h中定义在全局命名空间中的ceil()函数。 - Christian Askeland
@Christian - 如果你包含<cmath>(这本来就应该这样做),那么ceil将被包含在std命名空间中,这样你的问题就会消失。 - Charles Salvia
我刚刚完成了。问题消失了。是的,我应该一直使用<cmath>... - Christian Askeland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接