Boost.Range 对 ATL/WTL CString 的支持






4.12/5 (9投票s)
2005 年 9 月 2 日
2分钟阅读

37058

262
使用 Boost.Range 为 CString 提供一致的接口。
引言
Tomato.String 为 ATL/WTL CString
提供 Boost.Range 支持。 CString
不能是 Sequence 的模型,因为 Sequence 的需求是使用成员函数定义的。但是 Boost.Range 的概念有些新,并且是使用自由(非成员)函数定义的。 因此,通过使用本文,您可以将 CString
传递给任何接受 Random Access Range 的算法。
要求
- Microsoft Visual C++ .NET 7.1 版
- WTL 7.5 版
- Boost C++ 库 1.33.0 版(除非构建演示,否则无需编译)
- Ketchup Message Map Library(如果您想要最新版本)
快速开始
- 包含头文件
#include "ketchup/tomato/string.hpp"
- 调用算法
#include <boost/algorithm/string.hpp> void quick_start() { WTL::CString str(_T("hello range!")); boost::to_upper(str); ATLASSERT( str == _T("HELLO RANGE!") ); }
我将介绍一些 ATL/WTL CString
可以使用的算法。
Boost.String 算法
#include <boost/algorithm/string.hpp> void test_string_algo() { ATL::CFixedStringT<ATL::CString, 50> str(_T("123xxx321")); ATLASSERT( boost::starts_with(str, _T("123")) ); ATLASSERT( !boost::starts_with(str, _T("1234")) ); }
tomato::back_inserter
由于 ATL/WTL CString
无法符合 Sequence,因此您无法直接替换 CString
的字符。 但是您有 Output Iterator
#include "ketchup/tomato/iterator.hpp" void test_back_inserter() { ATL::CString strout; boost::replace_first_copy( tomato::back_inserter(strout), _T("1abc3abc2"), _T("abc"), _T("YYY")); ATLASSERT( strout == _T("1YYY3abc2") ); }
tomato::back_inserter
接受像 std::string
这样的 Back Insertion Sequence。
STL 算法
STL 算法也能很好地工作。由于 STL 不知道 Boost.Range 的概念,您需要 Boost.Range 函数包含的 boost::begin
和 end
的帮助
#include <algorithm> #include <boost/range.hpp> void test_std_algo() { WTL::CString str(_T("acbfdge")); std::sort(boost::begin(str), boost::end(str)); ATLASSERT( str == _T("abcdefg") ); }
所有接受 Random Access Iterator 的算法都可以工作。 请记住,Boost.Range 函数是 Container 的相应成员的替代品。 从现在开始,您不应使用诸如 GetBuffer
、GetString
和 begin
之类的成员。
Boost.Regex
Boost.Regex 已经 支持 ATL::CString
,但是我支持的 WTL::CString
缺失了
#include <boost/regex.hpp> // for boost::tregex #include <boost/regex/mfc.hpp> void test_regex() { WTL::CString str(_T("123a1cxxxa23cXXXa456c321")); boost::tregex rx(_T("a([0-9]+)c")); WTL::CString fmt(_T("_A$1C_")); WTL::CString strout = boost::regex_replace(str, rx, fmt); ATLASSERT( boost::equals( strout, _T("123_A1C_xxx_A23C_XXX_A456C_321")) ); }
另一种方法是使用 Boost.StringAlgorithm 提供的薄封装
#include <string> // yet required #include <boost/algorithm/string/regex.hpp> // for boost::tregex #include <boost/regex/mfc.hpp> void test_algo_regex() { // works around missing overloads typedef std::basic_string<TCHAR> fmt_string_t; ATL::CString str(_T("123a1cxxxa23cXXXa456c321")); boost::tregex rx(_T("a([0-9]+)c")); fmt_string_t fmt(_T("_A$1C_")); WTL::CString strout; boost::replace_regex_copy( tomato::back_inserter(strout), str, rx, fmt ); ATLASSERT( boost::equals( strout, _T("123_A1C_xxxa23cXXXa456c321")) ); }
关注点
为什么 CString
应该符合 Boost.Range 概念? 现在我们有三种字符串类型:std::string
、ATL::CString
和 WTL::CString
,在编写自己的算法时您会选择哪一个? 您会像可怜的 WTL 一样定义 _CSTRING_NS
吗? Boost.Range 解决了这些问题。
顺便说一句,为什么我们要为 STL 算法编写数百个 begin
和 end
? Boost.RangeEx(非官方)提供了薄封装函数
#include <boost/range_ex/algorithm.hpp> void test_range_algo() { WTL::CString str(_T("acbfdge")); boost::sort(str); ATLASSERT( str == _T("abcdefg") ); }
参考文献
- Tomato.String
- P-Stade
- Boost C++ Libraries
- Boost.Range
- Boost.RangeEx
- Boost.Regex
- Boost.StringAlgorithm
发行说明
- 0.90.0 版 - 初始版本。