简体   繁体   中英

What's the purpose of std::char_traits::assign()?

void assign(char_type& to, char_type from);

Why can't you just use the assignment operator instead of using this function ? What is this used for?

You actually use this function every time you use std::string :). std::string is actually a typedef for std::basic_string, which is defined as:

template< 
    class CharT, 
    class Traits = std::char_traits<CharT>, 
    class Allocator = std::allocator<CharT>
> class basic_string;

(see this ). Pay particular attention to the Traits template parameter. If you were so inclined, the Traits template parameter allows you to customize certain attributes of the string class's behavior. One of these properties is what happens when you make an assignment.

Here is an example usage of this. It will force assignments to be lowercase.

#include <string>
#include <iostream>
#include <cctype>

struct ci_char_traits : public std::char_traits<char> {
    static void assign(char& r, const char& a)
    {
        r = std::tolower(a);
    }

    static char* assign(char* p, std::size_t count, char a)
    {
        for (std::size_t i = 0; i < count; ++i)
        {
            p[i] = std::tolower(a);
        }
    }
};

typedef std::basic_string<char, ci_char_traits> ci_string;

std::ostream& operator<<(std::ostream& os, const ci_string& str) {
    return os.write(str.data(), str.size());
}

int main()
{
    ci_string s1 = "Hello";

    // This will become a lower-case 'o'
    s1.push_back('O');

    // Will replace 'He' with lower-case 'a'
    s1.replace(s1.begin(), s1.begin()+2, 1, 'A');

    std::cout << s1 << std::endl;
}

This is because character traits are a way to produce variants of standard classes (like strings) and a primitive type's operator may not actually be what you want.

For instance, consider a class that stores case-insensitive strings; you might implement assign() in a way that stores the same thing for both a capital letter and its lowercase version. (For that matter, other character-trait operations such as equality would have to be overridden too.)

You can write your own character class, and define its operator= . But, you may find it convenient to use fundamental character types such as char , wchar_t , char16_t , char32_t or char8_t . Such non-class types don't allow you to overload their operators, and so char_traits provides a way to customise a small set of their common operations (as suggested in other answers, this could allow case-insensitive character operations, for example).

template < 
  class CharT, 
  class Traits = std::char_traits<CharT>, 
  class Allocator = std::allocator<CharT>
> class basic_string;

std::basic_string is a good example; the second template parameter, Traits , allows access to such customisation. Consider also the third template parameter, Allocator , which allows the user of std::basic_string to customise how it allocates memory internally. This could lead to a similar question: why not just use operator new ?

Less significant, but note too that C++20 has introduced a second overload of std::char_traits<CharT>::assign :

static constexpr char_type* assign(char_type* p, std::size_t count, char_type a);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM