能否将std::byte回溯到C++14版本?

huangapple go评论113阅读模式
英文:

Is it possible to backport std::byte to C++14

问题

std::byte在C++17中定义如下:

enum class byte : unsigned char {};

我目前在使用C++14,我想知道如果我在C++14中添加相同的定义(在某个非std命名空间中,包括运算符重载等),这个新类型是否会像unsigned char一样具有相同的别名“free-pass”,或者我是否正在违反严格别名规则,从而导致未定义行为?

看起来似乎可以工作,但我想知道是否应该改用using byte = unsigned char;,但这会导致其他复杂性(例如,我无法区分字节和uint8_t)。

英文:

std::byte is defined in C++17 as:

enum class byte : unsigned char {};

I'm currently stuck at using C++14, and I wonder if I add the same definition in C++14 (in some non-std namespace, along with the operator overloads etc.), will this new type get the same aliasing "free-pass" as an unsigned char or I setting myself up for undefined behavior due to violating the strict aliasing rule?

It seems to work, but I'm wondering if I instead should go with using byte = unsigned char; which sadly causes other complications (for instance then I can't make a difference between a byte and uint8_t).

答案1

得分: 7

不,这是不可能的。别名例外只适用于charunsigned charstd::byte。你不能在标准C++中定义一个类型来获得它们的“超能力”。

可能有一些特定于编译器的属性可以给一个声明为

enum class byte : unsigned char {};

的类型提供等效的别名例外,尽管别名并不是唯一的异常行为。

从技术上讲,std::byteunsigned char也是核心语言中能够为其他对象提供存储空间的特殊例外类型,也是唯一能够在其类型的数组的生命周期开始时隐式创建对象的类型。其他类型都不能做到这两点。然而,在通常的C++实现中,这一部分可能在实践中并不是非常相关。

std::byteunsigned char(可能还有char)也是唯一一种在某些非常特定的情况下允许对不确定值进行操作的类型。但是,再次强调,在通常的C++实现中,这可能不会成为一个实际的问题。

对于数组new表达式,也有一个例外,它特别保证了charunsigned charstd::byte之间没有偏移量,即分配的起始位置和数组的起始位置是一致的。然而,在实践中,实现可能会将这个例外扩展到所有平凡类型。

英文:

No, it isn't possible. The aliasing exception is specific only to char, unsigned char and std::byte. You can't define a type in standard C++ to also gain their "superpower".

There may be compiler-specific attributes that can give a type declared with

enum class byte : unsigned char {};

equivalent aliasing exceptions, although aliasing isn't the only exceptional behavior either.

Technically std::byte and unsigned char are also specific exceptions in the core language that are able to provide storage for other objects and the only types that can cause implicit creation of objects when the lifetime of an array of their type starts. Other types can't do either. However, on the usual C++ implementations that part is probably not really all that relevant in practice.

std::byte and unsigned char (and potentially char) are also the only types for which it is sometimes allowed to operate on indeterminate values in some very specific circumstances. But again, on usual C++ implementations that probably isn't going to be a practical problem.

There is also an exception for array-new expressions that guarantees specifically only for char, unsigned char and std::byte that there is no offset between the beginning of the allocation and the beginning of the array. Again though, in practice implementations will probably extend this exception to all trivial types.

答案2

得分: 0

C++标准对程序没有强制性的规定要求,尽管在很多地方使用了这样的措辞(来自第4.1.1节:实现的一致性:通用):

尽管本文档仅对C++实现规定要求,但如果将这些要求表述为对程序、程序部分或程序执行的要求,往往更容易理解。这些要求具有以下含义:

...如果程序包含违反不需要诊断的规则的情况,本文档对实现不对该程序提出要求。

虽然C14不要求实现提供支持所描述功能的实际手段,但几乎所有实现都可以配置以一致的方式扩展语言的语义以支持这样的功能。Clang和gcc都使用-fno-strict-aliasing标志来实现这一目的。除非有特殊需要使用不支持此类扩展的编译器,否则在执行有益于这些扩展的任务时,使用这些扩展往往比不使用它们更安全,即使需要通过各种方式确保任何无错误的编译器都能正确处理代码。

英文:

The C++ Standard does not impose any normative requirements upon programs, despite the phraseology used in much of it (From section 4.1.1: Implementation compliance: General):

> Although this document states only requirements on C++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs. Such requirements have the following meaning:
>
> ... If a program contains a violation of a rule for which no diagnostic is required, this document places no requirement on implementations with respect to that program.

Although C14 does not require that implementations provide a practical means of supporting the described functionality, nearly all implementations can be configured to extend the semantics of the language to support such functionality in consistent fashion. Clang and gcc both use the -fno-strict-aliasing flag for that purpose. Unless one has a particular need to use a compiler which does not support such extensions, using such extensions when performing tasks that benefit them is apt to be safer than compiling without them even if one jumps through hoops to ensure that any bug-free compilers would be required to process one's code correctly.

huangapple
  • 本文由 发表于 2023年8月9日 17:17:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866262.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定