char_traits struct 初步学习

本文介绍了C++中的char_traits结构体,它定义了字符的特性并为字符操作提供语义。char_traits用于basic_string和iostream类,提供如eq、lt、compare等方法,允许重载以改变字符串的属性,如大小写敏感性。此外,char_traits隐藏了不同字符集的细节,如EOF值。通过traits,模板编程可以更加通用和灵活。

在学习文件读取时碰到文件尾字符 EOF 的问题,顺藤摸瓜找到 char_traits

msdn 上关于 EOF 的说明,就一句话:

Returns the end-of-file (EOF) character.

在注意中提到一句:

A value that represents end of file (such as EOF or WEOF).

意思是 EOF 表示的是文件尾的一个值,对于不同的字符集会对应不同的数值,但对用户来说就隐藏了这种细节。在给出的示例中也说明了这一点:

// char_traits_eof.cpp
// compile with: /EHsc
#include <string>
#include <iostream>

int main()
{
    using namespace std;

    char_traits<char>::char_type ch1 = 'x';
    char_traits<char>::int_type int1;
    int1 = char_traits<char>::to_int_type(ch1);
    cout << "char_type ch1 is '" << ch1 << "' and corresponds to int_type "
         << int1 << "." << endl << endl;

    char_traits<char>::int_type int2 = char_traits<char>::eof();
    cout << "The eof marker for char_traits<char> is: " << int2 << endl;

    char_traits<wchar_t>::int_type int3 = char_traits<wchar_t>::eof();
    cout << "The eof marker for char_traits<wchar_t> is: " << int3 << endl;
}
输出:

char_type ch1 is 'x' and corresponds to int_type 120.

The eof marker for char_traits<char> is: -1
The eof marker for char_traits<wchar_t> is: 65535

可以看到 char_traits 是模板类,在 cplusplus 上给出的解释是:

Character traits classes specify character properties and provide specific semantics for certain operations on characters and sequences of characters.

就是说 character traits 实例化了字符的各种性质(包括 eof 的数值,int_type, off_type, pos_type, state_type 等的 typedef),并提供对某些在字符和字符序列上特定操作的语义(语法?)。

简而言之,就是其中的 char_traits<char> 既是对字符集的实例化。

msdn 上给出的说明

template <
   class CharType
> struct char_traits;

The char_traits struct describes attributes associated with a character.

The template struct describes various character traits for type CharType. The template class basic_string as well as several iostream template classes, including basic_ios, use this information to manipulate elements of type CharType.

模板构造描述了 CharType 类型的各种特性,得到这种类型特性之后,就可以用这些信息来操作 CharType 类的元素。


还有相关博文:

char_traits

摘要:c++标准库中,有一个string,这个相信大家都知道,其实它是一个basic_string的一个typedef,其实在 msdn 这些地方,查 string 查不到什么太多东西,需要了解内部接口,得查basic_string
至于char_traits,是base_string的一个模板参数,它主要负责关于字符的属性和方法,譬如 eq、lt、compare、find 这些,比较字符大小,查找字符等等,这个类有什么用呢?
可以重载来改变string的一些字符相关的内部属性,譬如大小写敏感、字符串比较这些,具体的接口,而且,里面的接口基本上都是 static ,可以类似 strcpy、strlen 这样的接口直接使用(这个好像意义不大:P)

C++的Char traits模板类

摘要:字符特性模板,目的是提供最基本的字符特性的统一的方法函数。

C++ traits学习笔记(一)

摘要:traits是服务于泛型编程的,其目的是让模板更加通用,同时把一些细节向普通的模板用户隐藏起来。当用不同的类型去实例化一个模板时,不可避免有些类型会存在一些与众不同的属性,若考虑这些特性的话,可能会导致形成的模板不够“泛型”或是过于繁琐,而traits的作用是把这些特殊属性隐藏起来,从而实现让模板更加通用。


如有错误,恳请指正

In file included from /usr/include/c++/13/string:42, from /root/workspace/sylar/sylar/uri.h:13, from /root/workspace/sylar/sylar/uri.rl:1: In static member function ‘static std::char_traits<char>::char_type* std::char_traits<char>::copy(char_type*, const char_type*, std::size_t)’, inlined from ‘static void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy(_CharT*, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/13/bits/basic_string.h:430:21, inlined from ‘static void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy(_CharT*, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/13/bits/basic_string.h:425:7, inlined from ‘static void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy_chars(_CharT*, const _CharT*, const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/13/bits/basic_string.h:484:16, inlined from ‘void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_M_construct(_InIterator, _InIterator, std::forward_iterator_tag) [with _FwdIterator = const char*; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/13/bits/basic_string.tcc:247:21, inlined from ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/13/bits/basic_string.h:627:14, inlined from ‘static sylar::Uri::ptr sylar::Uri::Create(const std::string&)’ at /root/workspace/sylar/sylar/uri.rl:80:27: /usr/include/c++/13/bits/char_traits.h:435:56: error: argument 2 null where non-null expected [-Werror=nonnull] 435 | return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ /usr/include/c++/13/bits/char_traits.h:435:56: note: in a call to built-in function ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’
06-24
--------------------------------------------------------------------------- ArgumentError Traceback (most recent call last) <ipython-input-14-bfb9c7f9936a> in <module> 32 labeller = SementicRoleLabeller() 33 labeller.load(lab_model_path) ---> 34 roles = labeller.label(words, posttags, arcs) 35 36 for role in roles: ArgumentError: Python argument types in SementicRoleLabeller.label(SementicRoleLabeller, list, list, list) did not match C++ signature: label(struct SementicRoleLabeller {lvalue}, class boost::python::list, class boost::python::list, class std::vector<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > >) label(struct SementicRoleLabeller {lvalue}, class boost::python::list, class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >, class std::vector<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > >) label(struct SementicRoleLabeller {lvalue}, class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >, class boost::python::list, class std::vector<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > >) label(struct SementicRoleLabeller {lvalue}, class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >, class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >, class std::vector<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > >)
最新发布
10-28
### 关于 `std::char_traits` 的详细信息 `std::char_traits` 是 C++ 标准库中的一个模板类,用于描述字符类型的特性。它提供了一组静态成员函数和常量,这些函数和常量定义了如何比较、复制以及操作特定字符类型的行为[^3]。 以下是 `std::char_traits` 的主要功能及其常见用法: #### 1. 基本概念 `std::char_traits` 是标准字符串 (`std::string`) 和流对象 (如 `std::stringstream`, `std::ifstream`, `std::ofstream`) 中的核心组件之一。它的设计目的是为了支持多种字符集(如 ASCII、Unicode 等),并允许开发者自定义字符处理逻辑。 默认情况下,C++ 提供了针对不同字符类型的特化版本,例如: - `std::char_traits<char>`:适用于单字节字符。 - `std::char_traits<wchar_t>`:适用于宽字符。 - `std::char_traits<char16_t>` 和 `std::char_traits<char32_t>`:分别适用于 UTF-16 和 UTF-32 字符编码。 #### 2. 成员函数与常量 `std::char_traits` 定义了一系列静态成员函数和常量,用于实现常见的字符操作。以下是一些常用的成员函数: | 函数名 | 描述 | |---------------------|----------------------------------------------------------------------| | `assign(c1, c2)` | 将字符 `c2` 赋值给字符 `c1`。 | | `compare(s1, s2, n)`| 比较两个长度为 `n` 的字符数组 `s1` 和 `s2` 是否相等。 | | `copy(s1, s2, n)` | 将长度为 `n` 的字符数组 `s2` 复制到 `s1`。 | | `length(s)` | 返回字符数组 `s` 的长度。 | | `find(s, n, a)` | 在长度为 `n` 的字符数组 `s` 中查找第一个等于字符 `a` 的位置。 | | `eq(c1, c2)` | 判断字符 `c1` 和 `c2` 是否相等。 | | `lt(c1, c2)` | 判断字符 `c1` 是否小于字符 `c2`。 | 此外,还提供了几个重要的常量: - `eof()`:表示输入结束的特殊标记。 - `not_eof(c)`:判断字符 `c` 是否不等于 EOF。 #### 3. 自定义 `std::char_traits` 虽然大多数情况下可以直接使用标准库提供的特化版本,但在某些场景下可能需要自定义行为。可以通过继承或部分特化的方式重新定义 `std::char_traits` 的行为。例如: ```cpp template <> struct std::char_traits<MyCharType> { static constexpr MyCharType eof() { return MyCharType(-1); } static bool eq(MyCharType lhs, MyCharType rhs) { return lhs.value == rhs.value; } static void assign(MyCharType& dest, const MyCharType& src) { dest = src; } }; ``` 以上代码展示了如何为自定义字符类型 `MyCharType` 创建一个新的 `std::char_traits` 特化版本。 --- ### 链接错误的原因分析 当遇到类似于 `"undefined reference to std::__cxx11::basic_stringstream"` 或其他类似的链接器错误时,通常是因为以下几个原因之一[^2]: 1. **编译选项问题** 如果使用的 GCC 编译器启用了 `-D_GLIBCXX_USE_CXX11_ABI=0` 或者项目依赖项之间存在 ABI 不兼容的情况,则可能导致此类错误。 2. **缺少必要的库文件** 确保在链接阶段包含了所有必需的标准库文件。对于 GNU 工具链,默认会自动链接 `libstdc++.so`,但如果手动指定链接顺序或者遗漏了一些目标文件,也可能引发此问题。 3. **重复声明冲突** 当多个源码单元尝试定义同一个全局变量或函数时,可能会导致多重定义错误。这通常是由于头文件保护不当引起的。 解决这些问题的方法包括检查项目的构建脚本、调整编译参数以及验证第三方依赖的一致性。 --- ### 示例代码 下面是一个简单的例子,展示如何利用 `std::char_traits` 来创建自定义字符类型的支持: ```cpp #include <iostream> #include <sstream> // 自定义字符类型 struct MyChar { int value; friend bool operator==(const MyChar& lhs, const MyChar& rhs) { return lhs.value == rhs.value; } }; // 自定义 char_traits namespace std { template <> struct char_traits<MyChar> { typedef MyChar char_type; typedef ptrdiff_t off_type; typedef streamsize size_type; static constexpr MyChar eof() { return MyChar{-1}; } static bool eq(const MyChar& lhs, const MyChar& rhs) { return lhs == rhs; } static void assign(MyChar& dst, const MyChar& src) { dst.value = src.value; } }; } int main() { using CustomStringStream = std::basic_stringstream<MyChar>; CustomStringStream ss; MyChar ch{65}; // 'A' ss << ch; MyChar result; ss >> result; if (result == ch) { std::cout << "Characters match!" << std::endl; } else { std::cout << "Mismatch detected." << std::endl; } return 0; } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值