我们是一个C++ 库。多年来,我们在全局命名空间中使用 typedef unsigned char byte;
。用户程序和其他库提供了 byte
的兼容定义,因此没有问题。
C++17 添加了 std::byte
并改变了字节的语义。现在我们需要通过避免全局 namespace 污染来更加卫生;我们需要将自己与 std::byte
隔离开来。我们的更改是将我们的 byte
移到我们的命名空间中。
在测试更改的影响时,我们目睹了意外的失败。下面的程序没有遵循最佳实践(根据 Herb Sutter 在 Migrating to Namespaces 的说法),但我们希望它成为 的典型用例用户程序。
$ cat test2.cxx
#include "cryptlib.h"
#include <iostream>
using namespace std;
using namespace CryptoPP;
// Testing this to select the right byte type
using byte = CryptoPP::byte;
int main(int argc, char* argv[])
{
CryptoPP::byte block1[16];
std::byte block2[16];
byte block3[16];
return 0;
}
由于 std::byte
、CryptoPP::byte
和 using 命名空间,上面的程序具有
。正如我所说,我知道它还有一些不足之处。byte
的竞争定义...
编译程序结果(没有未使用的警告):
$ echo $CXXFLAGS
-DNDEBUG -g2 -O3 -std=c++17 -Wall -Wextra
$ g++ $CXXFLAGS test2.cxx ./libcryptopp.a -o test.exe
test2.cxx: In function ‘int main(int, char**)’:
test2.cxx:12:3: error: reference to ‘byte’ is ambiguous
byte block3[16];
^~~~
test2.cxx:6:28: note: candidates are: using byte = CryptoPP::byte
using byte = CryptoPP::byte;
^
In file included from stdcpp.h:48:0,
from cryptlib.h:97,
from test2.cxx:1:
/usr/include/c++/7/cstddef:64:14: note: enum class std::byte
enum class byte : unsigned char {};
^~~~
在编译错误中,令我吃惊的是,我们明确地使用 using byte = CryptoPP::byte;
消除了歧义。
我们希望建议在全局命名空间中依赖于 byte
的用户(以及使用 using namespace ....
声明的用户)使用 using byte = CryptoPP::byte;
直到他们有时间更新他们的代码。
我的第一个问题是,为什么编译器声称 byte
在被告知通过 using
使用 CryptoPP::byte
之后是不明确的> 声明?或者这完全是错误的,我们很幸运在编译过程中取得了这么大的进展?
第二个相关问题是,在我们将 byte
迁移到我们的命名空间后,我们是否可以向用户提供任何建议,以便他们现有的代码能够按预期进行编译?还是用户修复代码的唯一选择?
我认为这与问题有关:Context of using declaration and ambiguous declaration . using byte = CryptoPP::byte;
使我感到困惑,因为歧义已被消除。
关于下面的评论和“我认为可以从中吸取关于从一开始就智能使用命名空间的教训”,有一些背景故事。我是戴伟的Crypto++ .它写于 1990 年代初期,使用了无作用域的 byte
,因为 C++ 命名空间不可用。命名空间大约在 5 年后出现。
引入 namespace 后,除 byte
外,所有内容都移入了 CryptoPP
。根据source code comments , byte
由于“与其他字节类型定义的歧义” 而保留在全局命名空间中。显然,早在 C++17 之前就存在争论。早期的 C++ 编译器可能无法帮助解决这个问题。
事后看来,我们应该计划让某些版本的 C++ 执行此操作(除了糟糕的 using namespace ...
交互)。我们应该已经转移到 CryptoPP::byte
,并且可能提供了一个无作用域的 byte
以方便带有适当警告的用户程序。
后见之明总是 20/20。
最佳答案
全局命名空间中的using-directive causes unqualified name lookup to consider all declarations in the nominated namespace as members of the global namespace .它们与全局命名空间的其他成员处于平等地位,因此向全局命名空间添加额外的声明不会解决不合格查找中现有的歧义。
此类声明可以解决限定名称查找歧义(例如,在::byte
中查找byte
),因为that lookup only examines namespaces nominated by using-directives if a declaration is not found .这可能是您想到的地方。
关于c++ - 由于使用声明导致字节和歧义符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45125957/