Keywords: ISO C++ , library

Arbitrary Character Types
Prev | Chapter 13. String Classes | Next

## Arbitrary Character Types

The `std::basic_string` is tantalizingly general, in that it is parameterized on the type of the characters which it holds. In theory, you could whip up a Unicode character class and instantiate `std::basic_string<my_unicode_char>`, or assuming that integers are wider than characters on your platform, maybe just declare variables of type `std::basic_string<int>`.

That's the theory. Remember however that basic_string has additional type parameters, which take default arguments based on the character type (called `CharT` here):

          template <typename CharT,
                    typename Traits = char_traits<CharT>,
                    typename Alloc = allocator<CharT> >
          class basic_string { .... };

Now, `allocator<CharT>` will probably Do The Right Thing by default, unless you need to implement your own allocator for your characters.

But `char_traits` takes more work. The char_traits template is declared but not defined. That means there is only

          template <typename CharT>
            struct char_traits
            {
                static void foo (type1 x, type2 y);
                ...
            };

and functions such as char_traits<CharT>::foo() are not actually defined anywhere for the general case. The C++ standard permits this, because writing such a definition to fit all possible CharT's cannot be done.

The C++ standard also requires that char_traits be specialized for instantiations of `char` and `wchar_t`, and it is these template specializations that permit entities like `basic_string<char,char_traits<char>>` to work.

If you want to use character types other than char and wchar_t, such as `unsigned char` and `int`, you will need suitable specializations for them. For a time, in earlier versions of GCC, there was a mostly-correct implementation that let programmers be lazy but it broke under many situations, so it was removed. GCC 3.4 introduced a new implementation that mostly works and can be specialized even for `int` and other built-in types.

If you want to use your own special character class, then you have a lot of work to do, especially if you with to use i18n features (facets require traits information but don't have a traits argument).

Another example of how to specialize char_traits was given on the mailing list and at a later date was put into the file `include/ext/pod_char_traits.h`. We agree that the way it's used with basic_string (scroll down to main()) doesn't look nice, but that's because the nice-looking first attempt turned out to not be conforming C++, due to the rule that CharT must be a POD. (See how tricky this is?)

Prev | Up | Next
Case Sensitivity | Home | Tokenizing