5

It seems the following is guaranteed to pass (asked already here):

#include <type_traits>
static_assert(!std::is_same_v<char, signed char>);
static_assert(!std::is_same_v<char, unsigned char>);

To quote cppreference

[char] has the same representation and alignment as either signed char or unsigned char, but is always a distinct type

Is it also guaranteed that int8_t and uint8_t are defined in terms of the explicitly signed types not defined in terms of char, and therefore also form a set of 3 distinct types with char?

#include <cstdint>
#include <type_traits>
static_assert(!std::is_same_v<char, int8_t>);
static_assert(!std::is_same_v<char, uint8_t>);
Eric
  • 87,154
  • 48
  • 211
  • 332
  • I wouldn't expect standard to specify things which are hardly related, that would smell to me as over-specified. (and I somehow fail to see how int8/uint8 relate to char, except that char is highly likely represented by 8 bits too and you can cast between them safely, but none of that seems to me relevant to make the types same/non-same by standard. – Ped7g Aug 29 '19 at 07:15

2 Answers2

7

On your first point, yes, char, signed char, and unsigned char must always be distinct types.

On the second point, int8_t and uint8_t might be or might not be the same type as a char (or its signed or unsigned variants); i.e. there is no guarantee for or against.

Bathsheba
  • 220,365
  • 33
  • 331
  • 451
7

The fixed-width types are implementation-defined aliases. The (u)int8_t types are NOT guaranteed to be aliases for any of the fundamental char types at all. They are only guaranteed to be (un)signed 8-bit integer types. They MAY be aliases for (un)signed char, or they MAY be aliases for vendor-specific types, such as (un)signed __int8. It is up to each compiler vendor to decide what aliases best suits their implementation.

Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
  • I updated my question - what I'm hoping for is a guarantee that they are _not_ aliases of unqualified `char`, because if they are I cannot specialize a template for `char` without also matching one of those types. – Eric Aug 29 '19 at 07:22
  • 1
    @Eric: No, there's no such guarantee: `typedef char uint8_t;` would do if `char` is `unsigned`, although I'd conject that a *sensible* implementation would use `typedef unsigned char uint8_t;`. – Bathsheba Aug 29 '19 at 07:26
  • To some extent, I'd argue it's the job of the standard to _require_ a sensible implementation :). I suppose this is a very small thorn to spend committee time on though... – Eric Aug 29 '19 at 08:05
  • @Eric what's the precise issue, if the `char` specialization covers also one of those two types? Does it clash, if you add another two specializations for `uint8_t` and `int8_t`? That would sound like real problem to me, but I would *expect* the compiler then to treat that ambiguity by checking for the specific type of the specialization and treating all three of them as different type. clang 8.0.0 seems to do that: https://godbolt.org/z/gphsmB (for me this looks then as no-issue, because if your code wants to specialize for some type, it can) – Ped7g Aug 29 '19 at 08:52