basic_string literals

Does Boost offer any facility for declaring basic_string literals in templates, i.e. something like basic_string<CharType> s = BOOST_STRING("foo"); Thank you, Johan Råde

On 7/28/06 10:04 AM, "Johan Råde"
Does Boost offer any facility for declaring basic_string literals in templates, i.e. something like
basic_string<CharType> s = BOOST_STRING("foo");
No, it doesn't AFAIK. Would this provide anything useful if it did exist? It wouldn't be a literal, since "basic_string" isn't a built-in type. That means there is no compile-time savings; a string object is still created and it happens at run-time. What advantage would it have over something like: std::string s( "foo" ); If you really meant any "CharType" and not just "char", then a "BOOST_STRING" macro would have to reference a locale (probably the default global one) to perform a conversion. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com

Daryle Walker wrote:
On 7/28/06 10:04 AM, "Johan Råde"
wrote: Does Boost offer any facility for declaring basic_string literals in templates, i.e. something like
basic_string<CharType> s = BOOST_STRING("foo");
No, it doesn't AFAIK. Would this provide anything useful if it did exist? It wouldn't be a literal, since "basic_string" isn't a built-in type. That means there is no compile-time savings; a string object is still created and it happens at run-time. What advantage would it have over something like:
std::string s( "foo" );
If you really meant any "CharType" and not just "char", then a "BOOST_STRING" macro would have to reference a locale (probably the default global one) to perform a conversion.
Daryle, I ran into the problem when I wrote test cases for my facets for nonfinite numbers. I wanted to do something like: template<class CharType> void test() { basic_string<CharType> s1; ... some test code ... basic_string<CharType> s2 = "inf"; BOOST_ASSERT(s1 == s2); } This will of course only compile if CharType is char. How would you fix this code, so that it compiles both for char and wchar_t? This is what I eventually came up with: #define S_(a) string_literal_helper(a, L##a) class string_literal_helper { public: string_literal_helper(const char* s, const wchar_t* ws) : s_(s), ws_(ws) {} operator std::string() { return s_; } operator std::wstring() { return ws_; } private: const char* s_; const wchar_t* ws_; }; template<class CharType> void test() { basic_string<CharType> s1; ... some test code ... basic_string<CharType> s2 = S_("inf"); BOOST_ASSERT(s1 == s2); } Now the code compiles both for CharType = char and CharType = wchar_t. The idea is not mine. I have seen it somewhere on the web. --Johan Råde

Johan Råde wrote:
Daryle Walker wrote:
On 7/28/06 10:04 AM, "Johan Råde"
wrote: Does Boost offer any facility for declaring basic_string literals in templates, i.e. something like
basic_string<CharType> s = BOOST_STRING("foo"); No, it doesn't AFAIK. Would this provide anything useful if it did exist? It wouldn't be a literal, since "basic_string" isn't a built-in type. That means there is no compile-time savings; a string object is still created and it happens at run-time. What advantage would it have over something like:
std::string s( "foo" );
If you really meant any "CharType" and not just "char", then a "BOOST_STRING" macro would have to reference a locale (probably the default global one) to perform a conversion.
Daryle,
I ran into the problem when I wrote test cases for my facets for nonfinite numbers.
I wanted to do something like:
template<class CharType> void test() { basic_string<CharType> s1;
... some test code ...
basic_string<CharType> s2 = "inf"; BOOST_ASSERT(s1 == s2); }
This will of course only compile if CharType is char.
How would you fix this code, so that it compiles both for char and wchar_t?
This is what I eventually came up with:
#define S_(a) string_literal_helper(a, L##a)
class string_literal_helper { public: string_literal_helper(const char* s, const wchar_t* ws) : s_(s), ws_(ws) {} operator std::string() { return s_; } operator std::wstring() { return ws_; } private: const char* s_; const wchar_t* ws_; };
template<class CharType> void test() { basic_string<CharType> s1;
... some test code ...
basic_string<CharType> s2 = S_("inf"); BOOST_ASSERT(s1 == s2); }
Now the code compiles both for CharType = char and CharType = wchar_t. The idea is not mine. I have seen it somewhere on the web.
I once brought up this problem on comp.std.c++. Someone suggested, along
the lines I was thinking, that C++ have a literal_cast<type>(literal
expression) to cast a literal from one type to another using type
notation. This would parallel the other C++ casts, such as static_cast
and dynamic_cast.
The notation L'char' ( and L"char-string" ), to cast from a narrow
character ( character string ) to a wide character ( wide character
string ) does not work nicely with templates as you have discovered,
whereas a literal_cast<type>(expression) would do so, ie
literal_cast

On 7/29/06, Edward Diener
[snipped]
I once brought up this problem on comp.std.c++. Someone suggested, along the lines I was thinking, that C++ have a literal_cast<type>(literal expression) to cast a literal from one type to another using type notation. This would parallel the other C++ casts, such as static_cast and dynamic_cast.
The notation L'char' ( and L"char-string" ), to cast from a narrow character ( character string ) to a wide character ( wide character string ) does not work nicely with templates as you have discovered, whereas a literal_cast<type>(expression) would do so, ie literal_cast
('char') ( or literal_cast<wstring>("char-string") ). In the literal_cast case, of course, one could use a character ( or string ) template type as the type passed to literal_cast and an equivalent narrow character or narrow string value, and always be guaranteed of the correct result. Of course literal_cast, if it existed, would work with any types which are currently represented as a literal in C++, but needless to say its main use would be to go from the C language L'' ( L"" ) notation to a notation that worked correctly and effortlessly in template code.
However I have never written up such a suggestion to the C++ standard comittee. I still find the idea correct, however.
I believe that's really the best way to implement this functionality. It would mimic lexical_cast interface too, which is already part of boost. best regards, -- Felipe Magno de Almeida

Daryle Walker wrote:
On 7/28/06 10:04 AM, "Johan Råde"
wrote: Does Boost offer any facility for declaring basic_string literals in templates, i.e. something like
basic_string<CharType> s = BOOST_STRING("foo");
No, it doesn't AFAIK. Would this provide anything useful if it did exist? It wouldn't be a literal, since "basic_string" isn't a built-in type. That means there is no compile-time savings; a string object is still created and it happens at run-time. What advantage would it have over something like:
std::string s( "foo" );
If you really meant any "CharType" and not just "char", then a "BOOST_STRING" macro would have to reference a locale (probably the default global one) to perform a conversion.
I agree that "basic_string literal" is incorrect terminology. I should have asked, "How do I initialize an object of type basic_string<CharType> with a string literal?" Does Boost provide any nifty way of doing it? --Johan Råde

Johan Råde wrote: Now I have improved the macro so that one can write template<class CharType> void f() { CharType c = S_('a'); basic_string<CharType> s = S_("a"); } and the code will compile both for CharType = char and CharType = wchar_t. Why is this relevant to Boost? There are several Boost libraries that deal with strings that are templatized on the character type. Such libraries should come with tests that also are templatized on the character type. But when you write such tests, it is convenient to have a version of char s = 'a' and string s = "a" that works in templates. --Johan Råde ------------------------------------- Here is the improved macro: #define S_(a) make_literal_helper(a, L##a) class char_literal_helper { public: char_literal_helper(char c, wchar_t wc) : c_(c), wc_(wc) {} operator char() { return c_; } operator wchar_t() { return wc_; } private: const char c_; const wchar_t wc_; }; class string_literal_helper { public: string_literal_helper(const char* s, const wchar_t* ws) : s_(s), ws_(ws) {} operator std::string() { return s_; } operator std::wstring() { return ws_; } private: const char* s_; const wchar_t* ws_; }; inline char_literal_helper make_literal_helper(char c, wchar_t wc) { return char_literal_helper(c, wc); } inline string_literal_helper make_literal_helper(char* s, wchar_t* ws) { return string_literal_helper(s, ws); }
participants (4)
-
Daryle Walker
-
Edward Diener
-
Felipe Magno de Almeida
-
Johan Råde