Problem:
Using std::basic_string the extensible way
I'm writing a class that contains a string. But I decided to make it
more extensible and turn it into a class template:
template<typename CharT>
class My
{
std::basic_string<CharT> text;
};
How do I operate on such a string, so that it will work for any valid
instantiation of basic_string? For example, I'd like to append some text
to the end of the string or check if the first letter is lowercase.
Currently I'm doing:
text += "some other text";
For wstring I should probably do:
test += L"some other text";
How do I do it in a generic way?
Solution:
That depends on the meaning of these literals.
Are these only some selected literals of the
corresponding character type with a special
meaning? If so, than a character-depending
policy/traits class would be reasonable, which
would be explicitely specialized for the corresponding
value, e.g.
template <typename CharT>
class MyTraits;
template <>
struct MyTraits<char> {
static const char* append() {
return "some other text";
}
};
template <>
struct MyTraits<wchar_t> {
static const wchar_t* append() {
return L"some other text";
}
};
template<typename CharT>
class My
{
std::basic_string<CharT> text;
typedef MyTraits<CharT> Traits;
void foo() {
text += Traits::append();
}
};
Otherwise you could only declare the member
functions in the My class template and explicitely
specialize them for the corresponding character
type:
template<typename CharT>
class My
{
std::basic_string<CharT> text;
public:
void foo(); // Only declared, not defined
};
template<>
void My<char>::foo() {
text += "some other text";
}
template<>
void My<wchar_t>::foo() {
text += L"some other text";
}
In both cases some preprocessor magic
can help reducing the redundancies.
----------------------------------------------------------------------------
How about writing a helper function to convert a narrow string literal
to an arbitrary basic_string<T>:
// A template to 'widen' a string literal
template < class CharT >
std::basic_string<CharT> widen( char const* str ) {
std::basic_stringstream< CharT > s;
s << str; return s.str();
}
Then you can do
test += widen<char>( "foo bar" );
or
test += widen<wchar_t>( "foo bar" );
as appropriate.
You could even make it a constructor, but it's probably best to make it
explicit in the code when you want this widening.
Using std::basic_string the extensible way
I'm writing a class that contains a string. But I decided to make it
more extensible and turn it into a class template:
template<typename CharT>
class My
{
std::basic_string<CharT> text;
};
How do I operate on such a string, so that it will work for any valid
instantiation of basic_string? For example, I'd like to append some text
to the end of the string or check if the first letter is lowercase.
Currently I'm doing:
text += "some other text";
For wstring I should probably do:
test += L"some other text";
How do I do it in a generic way?
Solution:
That depends on the meaning of these literals.
Are these only some selected literals of the
corresponding character type with a special
meaning? If so, than a character-depending
policy/traits class would be reasonable, which
would be explicitely specialized for the corresponding
value, e.g.
template <typename CharT>
class MyTraits;
template <>
struct MyTraits<char> {
static const char* append() {
return "some other text";
}
};
template <>
struct MyTraits<wchar_t> {
static const wchar_t* append() {
return L"some other text";
}
};
template<typename CharT>
class My
{
std::basic_string<CharT> text;
typedef MyTraits<CharT> Traits;
void foo() {
text += Traits::append();
}
}; 
Otherwise you could only declare the member
functions in the My class template and explicitely
specialize them for the corresponding character
type:
template<typename CharT>
class My
{
std::basic_string<CharT> text;
public:
void foo(); // Only declared, not defined
};
template<>
void My<char>::foo() {
text += "some other text";
}
template<>
void My<wchar_t>::foo() {
text += L"some other text";
} 
In both cases some preprocessor magic
can help reducing the redundancies.
----------------------------------------------------------------------------
How about writing a helper function to convert a narrow string literal
to an arbitrary basic_string<T>:
// A template to 'widen' a string literal
template < class CharT >
std::basic_string<CharT> widen( char const* str ) {
std::basic_stringstream< CharT > s;
s << str; return s.str();
}
Then you can do
test += widen<char>( "foo bar" );
or
test += widen<wchar_t>( "foo bar" ); 
as appropriate.
You could even make it a constructor, but it's probably best to make it
explicit in the code when you want this widening.
本文介绍了一种使用模板类实现字符串泛型操作的方法,通过特性类和显式特化技术,可以为不同字符类型提供特定的字符串操作。同时,还提供了一个辅助函数用于将窄字符串字面量转换为任意基本字符串。
struct MyTraits
4万+

被折叠的 条评论
为什么被折叠?



