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?)