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?
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?
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 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;
}
You can write your own character class, and define its
operator=
. But, you may find it convenient to use fundamental character types such aschar
,wchar_t
,char16_t
,char32_t
orchar8_t
. Such non-class types don't allow you to overload their operators, and sochar_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).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 ofstd::basic_string
to customise how it allocates memory internally. This could lead to a similar question: why not just useoperator new
?Less significant, but note too that C++20 has introduced a second overload of
std::char_traits<CharT>::assign
: