Introduction
Tomato.String provides Boost.Range support for ATL/WTL CString
. CString
cannot be a model of Sequence, because Sequence requirements are defined using member functions. But Boost.Range concepts are somewhat new and those are defined using free (non-member) functions. So you can pass CString
to any algorithm that accepts Random Access Range by using this article.
Requirements
Quick start
- Include the header:
#include "ketchup/tomato/string.hpp"
- Call algorithms:
#include <boost/algorithm/string.hpp>
void quick_start()
{
WTL::CString str(_T("hello range!"));
boost::to_upper(str);
ATLASSERT( str == _T("HELLO RANGE!") );
}
I'll introduce some algorithms that ATL/WTL CString
can work with.
Boost.String algorithm
Boost.StringAlgorithm works well:
#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
As ATL/WTL CString
cannot conform to Sequence, you cannot directly replace characters of CString
. But you have the 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
accepts Back Insertion Sequence like std::string
.
STL algorithms
STL algorithms also work well. As STL doesn't know the Boost.Range concepts, you need the help of boost::begin
and end
that Boost.Range functions contain:
#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") );
}
All the algorithms that accept Random Access Iterator can work. Keep in mind that Boost.Range functions are replacements for the corresponding members of Container. You shouldn't use members like GetBuffer
, GetString
and begin
from here on.
Boost.Regex
Boost.Regex already supports ATL::CString
, but WTL::CString
that I support is missing:
#include <boost/regex.hpp>
#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")) );
}
Another way is to use the thin wrappers that Boost.StringAlgorithm provides:
#include <string>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex/mfc.hpp>
void test_algo_regex()
{
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")) );
}
Points of interest
Why CString
should conform to Boost.Range concept? Now that we have three string types; std::string
, ATL::CString
and WTL::CString
, which one will you select while writing your own algorithm? Will you define _CSTRING_NS
like poor WTL? Boost.Range solves these problems.
By the way, why should we write hundreds of begin
and end
for STL algorithms? Boost.RangeEx (unofficial) provides thin wrapper functions:
#include <boost/range_ex/algorithm.hpp>
void test_range_algo()
{
WTL::CString str(_T("acbfdge"));
boost::sort(str);
ATLASSERT( str == _T("abcdefg") );
}
References
Release notes
- Version 0.90.0 - Initial release.