c++stdstringchar-traits

Why does std::basic_string have two separate template parameters _Elem (char type) and _Traits (char traits)?


The problem is I don't understand why those should be separate. Why not use one class, like CharType, that would contain both the logic of char traits and char type. I mean replace that:

template <class _Elem, class _Traits = char_traits<_Elem>, class _Alloc = allocator<_Elem>>
class basic_string { /*...*/ };

with that:

template <class ExtendedTraits, class _Alloc = allocator<_Elem>>
class basic_string { /*...*/ };

where ExtendedTraits is the presaid combination of _Elem and _Traits, that might look like that:

template<_CharType> //all the necessary template parameters
class extended_traits 
{
public:
    using value_type = _CharType;
private:
    _CharType _elem;
public:
//... all methods, that used to be in char_traits but now non-static and accepting one parameter

};

I tried to implement both approaches, both of them do work, but there may be some problems I still do not notice.


Solution

  • I think it makes more sense to separate the character type from the Traits object. Traits is an additional class for character comparisons and such, which is inherently different from the character type. Your method would work, but the equivalent would be like combining two completely different functions into the same function.

    It's also more immediately obvious what character type the string is using. For example:

    typedef string basic_string<char>;
    

    is much more obvious than

    typedef string basic_char<extended_traits<char>, ...>;
    

    as there is an additional level of nesting and more characters and such.

    At the end of the day, we don't care about what Traits is, we care about what character type the string is. Traits is for internal operations, and is meant to be abstracted away; as such, it's kept away from the character type, which is meant to be more obvious as it indicates what types of values the string can contain.

    At least, that's my view on things.

    Besides, it's not necessarily a bad thing to have more template arguments for std::basic_string, especially since there's only ever one template argument you really need to define a parameter for - the other template are given default types. It's not often that I would need to define my own Traits class. But if I wanted to define my own separate string class with a custom character or something like that, I would have to define a Traits class for it, even if I have written my assignment operator and comparison operators and everything else. That would be especially irritating.