c++ - 嵌套与全局上下文中同级命名空间之间的区别
问题描述
我有一些使用嵌套命名空间编写的 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)
是模棱两可的。
我有两个问题
- 为什么现在模棱两可而不是第一个版本?
- 是否有可能在不明确列出所有函数的情况下获得我们之前的行为
using Sibling1::cos
?
解决方案
如您所描述的,该问题无法重现。此外,如果您在兄弟姐妹中使用您在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
命名空间中注入真正需要的函数,它们在兄弟姐妹中可用,从而避免通过注入不必要的函数的名称而引入的歧义。
推荐阅读
- java - 9999之后如何继续生成这个系列(xyz*3)==zzz
- javascript - 如何在帧图像内渲染屏幕截图/图像而不会流过帧?
- oop - 在 Dart 中,是否可以在单例中传递参数?
- regex - RegEx 用于匹配除开头和结尾的重复字符之外的所有内容
- python-3.x - 在 Windows 上执行 PyInstaller 创建的包时出现 ModuleNotFound 错误
- objective-c - NSSet 不包含对象,即使它们相等
- twitter - 如何使用 Twitter API 提取手动注释的推文?
- python - Python sqlite3 数据库包装器中需要游标对象吗?
- sql - 如何更改“WHERE startdate >= date”子句的值并获取一系列日期的数据?
- database - 达到时间戳时的 Postgresql 触发器