Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fully emulating missing distinct builtin types (specifically: char16_t and char32_t)

C++11 has two new character integral data types, char16_t and char32_t. I would like to emulate them for compilers that don't have a distinct type in order to overload I/O operations to see them a characters instead of their integer value.

These are the requirements:

  • Distinct (no typedef).
  • exact-width on normal systems (ala uint16_t and uint32_t)
  • other C++11 features are allowed (see below first attempt)
  • Must play nice with literals; char16_t c16 = u"blabla unicode text blabla"; must work.
  • if char16_t can be used in math operators, obviously this needs to function as well.

My first attempt which fails in the literal department was a strongly typed enum:

enum char16_t : uint16_t;

This has other drawbacks as well, that could perhaps be resolved by supplying the necessary operators myself (which is really fine by me).

like image 744
rubenvb Avatar asked Jan 05 '12 18:01

rubenvb


1 Answers

I don't think you will get the initialization to work because there isn't much scope to get it to work. The problem is that the initialization you are using in your example isn't supposed to work: the string literal u"..." yields an an array of char16_t const objects and you want to initialize a pointer with it:

char16_t const* c16 = u"...";

Also, without implementation of char16_t in the compiler it is very unlikely to support char16_t string literals. The best you could achieve is to play macro tricks which are intended to do the Right Thing. For now, you'd use e.g. wide character literals and when you get a compiler which support char16_t you just change the macro to use char16_t literals. Even for this to work you might need to use a record type which is bigger than 16 bit because wchar_t uses 32 bits on some platforms.

#define CONCAT(a,b) a##b

#if defined(HAS_C16)
#  define C16S(s) CONCAT(u,s)
#else
#  define C16S(s) reinterpret_cast<char16_t const*>(CONCAT(L,s));
struct char16_t
{
    unsigned short value;
};
#endif


int main()
{
    char16_t const* c16 = C16S("...");
}

Obviously, you still need to provide all kinds of operators e.g. to make integer arithmetic and suitable conversions work.

like image 78
Dietmar Kühl Avatar answered Oct 05 '22 21:10

Dietmar Kühl