字节和模棱两可的符号由于使用声明? [英] byte and ambiguous symbol due to using declarations?

查看:275
本文介绍了字节和模棱两可的符号由于使用声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们是 C ++库 .多年来,我们在全局名称空间中都有typedef unsigned char byte;.用户程序和其他库提供了byte的兼容定义,因此没有问题.

We are a C++ library. For years we had typedef unsigned char byte; in the global namespace. User programs and other libraries provided compatible definitions of byte, so there were no problems.

C ++ 17添加了std::byte并更改了字节的语义.现在,我们需要更加卫生,避免全局命名空间污染.并且我们需要使自己与std::byte隔离.我们的更改是将byte移到我们的命名空间中.

C++17 added std::byte and changed semantics of a byte. Now we need to be more hygienic by avoid global namespace pollution; and we need to insulate ourselves from std::byte. Our change is to move our byte into our namespace.

在测试变更的影响时,我们目睹了意外的失败. 下面的程序不遵循最佳做法(根据

We are witnessing an unexpected failure as we test the impact of changes. The program below does not follow best practices (according to Herb Sutter at Migrating to Namespaces), but we expect it to be a typical use case for user programs.

$ 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::byteCryptoPP::byteusing namespace ...,上面的程序具有竞争的byte定义.正如我说的,我知道这还有一些不足之处.

The program above has competing definitions of byte due to std::byte, CryptoPP::byte and the using namespace .... As I said, I know it leaves something to be desired.

编译程序会导致(消除未使用的警告):

Compiling the program results in (sans the unused warnings):

$ 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;的歧义.

In the compile error, what is catching me by surprise is, we explicitly removed the ambiguity with using byte = CryptoPP::byte;.

我们希望建议在全局命名空间中依赖byte的用户(以及使用using namespace ....声明的用户)使用using byte = CryptoPP::byte;,直到他们有时间更新其代码为止.

We hoped to advise users who depend upon byte in the global namespace (and who use the using namespace .... declarations) to use using byte = CryptoPP::byte; until they had time to update their code.

我的第一个问题是,为什么编译器在通过using声明被告知使用CryptoPP::byte后声称byte是模棱两可的?还是这纯粹是错误的,而我们很幸运在编译过程中走了这么远?

My first question is, why is the compiler claiming byte is ambiguous after it was told the to use CryptoPP::byte via the using declaration? Or is this just plain wrong, and we are lucky we got that far along during the compile?

第二个相关问题是,在将byte迁移到命名空间后,我们可以向用户提供任何建议以使他们的现有代码按预期进行编译吗?还是用户修复其代码的唯一选择?

A second related question is, is there any advice we can give to users so their existing code compiles as expected after we migrate byte into our namespace? Or is the only choice for users to fix their code?

我认为这与以下问题有关:使用声明和歧义声明的上下文.自从消除歧义后,using byte = CryptoPP::byte;绊倒了我.

I think this has something to do with the issue: Context of using declaration and ambiguous declaration. The using byte = CryptoPP::byte; is tripping me up since the ambiguity was removed.

关于下面的评论和我认为,从一开始就可以聪明地使用名称空间来吸取教训" ,其中有一些背景知识.这是戴伟的 Crypto ++ .它是在1990年代初期编写的,并使用了无作用域的byte,因为C ++名称空间不可用.命名空间大约在5年后出现.

Regarding comments below and "I think there's a lesson to be learned from this about intelligent use of namesapces from the get-go", there's some backstory. This is Wei Dai's Crypto++. It was written in the early 1990s, and used unscoped byte because C++ namespaces were not available. Namespaces appeared about 5 years later.

引入名称空间后,除byte之外的所有内容都移到了CryptoPP中.根据源代码注释byte仍保留在全局名称空间是由于与其他字节typedef有歧义" .显然,早在C ++ 17之前就有了争论.早期的C ++编译器可能无法解决问题.

When namespaces were introduced, everything was moved into CryptoPP except byte. According to source code comments, byte remained in global namespace due to "ambiguity with other byte typedefs". Apparently, there was contention long before C++17. Early C++ compilers probably did not help the issue.

事后看来,我们应该计划使用某些版本的C ++进行此操作(除了不良的using namespace ...交互作用之外).我们应该已经移至CryptoPP::byte,并且可能提供了一个不受范围限制的byte,以方便用户程序并带有适当的警告.

In hindsight, we should have planned for some version of C++ doing this (in addition to a bad using namespace ... interaction). We should have already moved to CryptoPP::byte, and possibly provided an unscoped byte for convenience to user programs with appropriate warnings.

Hindsight始终为20/20.

Hindsight is always 20/20.

推荐答案

全局命名空间using-directive /basic.lookup.unqual#2"rel =" noreferrer>使不合格的名称查找将提名的命名空间中的所有声明视为全局命名空间的成员.它们与全局名称空间的其他成员处于平等地位,因此向全局名称空间添加其他声明将无法解决不合格查找中的现有歧义.

A using-directive in the global namespace causes unqualified name lookup to consider all declarations in the nominated namespace as members of the global namespace. They stand on equal footing with other members of the global namespace, and so adding additional declarations to the global namespace will not resolve an existing ambiguity in unqualified lookup.

这样的声明可以解决限定名称查找的歧义(例如,在::byte中对byte的查找),因为

Such declarations can resolve qualified name lookup ambiguities (e.g., the lookup of byte in ::byte), because that lookup only examines namespaces nominated by using-directives if a declaration is not found. That might be where you got the idea.

这篇关于字节和模棱两可的符号由于使用声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆