40

As discussed at Why is nullptr_t not a keyword, it is better to avoid introducing new keywords because they can break backward compatibility.

Why then are char16_t and char32_t keywords, when they could just as well have been defined like so?

namespace std {
    typedef decltype(u'q') char16_t;
    typedef decltype(U'q') char32_t;
}
Community
  • 1
  • 1
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 1
    It's new to me these aren't typedefs anymore. Where did you get that claim from? – πάντα ῥεῖ May 28 '16 at 08:19
  • 2
    @πάνταῥεῖ They are listed as keywords in the standard. – Brian Bi May 28 '16 at 08:21
  • @πάνταῥεῖ: C++11 says they're keywords. (§2.12) – cHao May 28 '16 at 08:22
  • `char16_t` and `char32_t` are fundamental types, they aren't declared in `std`, I suppose you could argue that they could have been but presumably the working group wanted them as part of the C++ core. – user657267 May 28 '16 at 08:23
  • 4
    @user657267 The discrepancy between those types and `nullptr_t` is what puzzles me. This could've been a mere oversight, but I find it unlikely that nobody on the committee proposed making `char16_t` and `char32_t` *not* keywords. – Brian Bi May 28 '16 at 08:25
  • +1 but actually it would have been quite disturbing using `std::char32_t` all around instead of `char32_t`. That said, good question. – skypjack May 28 '16 at 08:27
  • I *think* this has to do with C compatibility, which defines the same two types. – user657267 May 28 '16 at 08:35
  • @user657267 That seems like a possible rationale, although not a compelling one since it does not seem that C++ was designed to be compatible with features added to C after C++98. For example, there is no `_Complex` in C++. – Brian Bi May 28 '16 at 08:40
  • I guess they want legal C codes that uses `typedef uint_least32_t char32_t;` to fail loudly. – cpplearner May 28 '16 at 08:42
  • 3
    The wchar_t debacle ought to be inspirational. If it would be a typedef then somebody can #include a .h file that makes it something else and you're back to having no use for it. – Hans Passant May 28 '16 at 09:55
  • @Brian The fact that there's no `_Complex` in C++ means it _is_ compatible. The name in C doesn't conflict with the name of something different in C++. – Oktalist May 28 '16 at 12:33
  • Isn't the answer to this question inherently based on the opinions of people we may not have access to? http://meta.stackoverflow.com/questions/323334/is-asking-why-on-language-specifications-still-considered-as-primarily-opinio – Barry May 28 '16 at 16:05

2 Answers2

25

The proposal itself explains why: to allow overloading with the underlying types of uint_least16_t and uint_least32_t. If they were typedefed this wouldn't be possible.

Define char16_t to be a distinct new type, that has the same size and representation as uint_least16_t. Likewise, define char32_t to be a distinct new type, that has the same size and representation as uint_least32_t.

[N1040 defined char16_t and char32_t as typedefs to uint_least16_t and uint_least32_t, which make overloading on these characters impossible.]

As for why they aren't in the std namespace, this is for compatibility with the original C proposal. C++ prohibits the C definitions from appearing in its own version of <cuchar>

[c.strings] / 3

The headers shall not define the types char16_t, char32_t, and wchar_t (2.11).

The types then would need to be global typedefs, which carries its own set of issues such as

typedef decltype(u'q') char16_t;

namespace foo {
  typedef int char16_t;
}

The reason for std::nullptr_t not being a keyword can be found in the question you linked

We do not expect to see much direct use of nullptr_t in real programs.

making nullptr_t the real exception here.

Community
  • 1
  • 1
user657267
  • 20,568
  • 5
  • 58
  • 77
1

Because of naughty code like this:

typedef uint16_t char16_t;

extern char * strndup16to8 (const char16_t* s, size_t n);
extern size_t strnlen16to8 (const char16_t* s, size_t n);

Sure, the existence of C++11 aware compilers doesn't preclude the existence of C++03 libraries or the plethora of systems or users that use C++03 compilers/libraries.

If you're lucky, they'll do this:

#if __STDC_VERSION__ < 201112L && __cplusplus < 201103L
   typedef uint16_t char16_t;
#endif