首页 > 解决方案 > 嵌套与全局上下文中同级命名空间之间的区别

问题描述

我有一些使用嵌套命名空间编写的 C++ 库。这些库使用许多数学函数,为了便于阅读,最好在不明确指定命名空间的情况下阅读这些函数。现在,代码的简化版本看起来像这样。

namespace Base::Sibling1 {
  float cos(float x) { return cosf(x); }
};

namespace Base::Sibling2 {
  using namespace Sibling1;
  float f(float x) { return cos(x); }
};

我们想改用更扁平的命名空间,主要是为了更容易用兄弟代码扩展库。我们曾希望像这样的简单更改会起作用:

namespace Sibling1 {
  float cos(float x) { return cosf(x); }
};

namespace Sibling2 {
  using namespace Sibling1;
  float f(float x) { return cos(x); }
};

相反,这现在失败了,因为现在的Sibling2::f()调用cos(x)是模棱两可的。

我有两个问题

  1. 为什么现在模棱两可而不是第一个版本?
  2. 是否有可能在不明确列出所有函数的情况下获得我们之前的行为using Sibling1::cos

标签: c++namespaces

解决方案


如您所描述的,该问题无法重现。此外,如果您在兄弟姐妹中使用您在Base. 因此,根本原因可能在于您未显示的代码的某些部分。

第二个版本没有定义cosf(),所以你可能正在使用一些命名空间。如果在该名称空间中还有一个,则cos()您会在两个重载之间产生歧义。我可以通过使用命名空间重现这一点std

#include <iostream>
#include <cmath>
using namespace std;
namespace Sibling1 {
  float cos(float x) { return cosf(x); }
}
namespace Sibling2 {
  using namespace Sibling1;
  float f(float x) { return cos(x); }
}

在线演示:编译错误表明哪些是歧义背后的候选者。如果您现在注释掉using namespace,歧义就会消失,并且代码可以编译。 网上证明

命名空间旨在避免命名冲突并控制歧义:

  • 创建一个命名空间并using namespace在任何地方都系统地破坏了整个目的。
  • 另一方面,长using列表很难维护,尤其是当您必须在多个同级命名空间中重复它们时。这可能是Base最初创建和嵌套的原因。

在第一个版本中,您不显示Base. 可能会在using其中使用一些更定制的子句而不是完整的命名空间:如果有选择地在Base命名空间中注入真正需要的函数,它们在兄弟姐妹中可用,从而避免通过注入不必要的函数的名称而引入的歧义。


推荐阅读