| Document number: | N3431=12-0121 |
| Date: | 2012-09-21 |
| Project: | Programming Language C++ |
| Reply-to: | Beman Dawes <bdawes at acm dot org> |
This proposal is suitable for a standard library Technical Specification. It is a pure addition that changes no current standard library headers and will break no existing code, assuming disciplined use of namespaces. It has based on Boost code that has been shipping for approximately two years, but has not been formally reviewed.
C++ standard library stream I/O for strings that contain embedded spaces can produce unexpected results. For example,
std::stringstream ss; std::string original = "foolish me"; std::string round_trip; ss << original; ss >> round_trip; std::cout << original; // outputs: foolish me std::cout << round_trip; // outputs: foolish assert(original == round_trip); // assert will fire
The proposed quoted stream I/O manipulator places delimiters, defaulted
to
double-quote ("), around strings on output, and strips off
the delimiters on input. This ensures strings with embedded white space round-trip as
desired. For example,
std::stringstream ss; std::string original = "foolish me"; std::string round_trip; ss << quoted(original); ss >> quoted(round_trip); std::cout << original; // outputs: foolish me std::cout << round_trip; // outputs: foolish me assert(original == round_trip); // assert will not fire
If the string contains the delimiter character, on output that character will
be preceded by an escape character, default to backslash (\), as will the escape character itself:
std::cout << quoted("She said \"Hi!\""); // outputs: "She said \"Hi!\""
namespace std
{
namespace tbd
{
template <class charT, class traits, class Allocator>
unspecified-type1 quoted(const std::basic_string<charT, traits, Allocator>& s,
charT delim='\"', charT escape='\\');
template <class charT>
unspecified-type2 quoted(const charT* s,
charT delim='\"', charT escape='\\');
template <class charT, class traits, class Allocator>
unspecified-type3 quoted(std::basic_string<charT, traits, Allocator>& s,
charT delim='\"', charT escape='\\');
}
}
unspecified_type1
and unspecified_type2 are implementation supplied
types with implementation supplied operator<<:
template <class charT, class traits> std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, constunspecified_typeN& proxy);Effects: Inserts characters into
os:
delim.- Each character in
string. If the character to be output is equal toescapeordelim, as determined byoperator==, first outputescape.delim.Remarks:
string,escape, anddelimhave the type and value of the corresponding arguments of the call to thequotedfunction that constructedproxy.Returns:
os.
unspecified_type3 is an implementation supplied
type with an implementation supplied operator>>:
template <class charT, class traits> std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, constunspecified_type3& proxy);Effects: Extracts characters from
os:
- If the first character extracted is equal to delim, as determined by
operator==, then:
- Turn off the
skipwsflag.string.clear()- Until an unescaped
delimcharacter is reached oris.not_good(), extract characters fromosand append them tostring, except that if anescapeis reached, ignore it and append the next character tostring.- Discard the final
delimcharacter.- Restore the
skipwsflag to its original value.- Otherwise,
os >> string.Remarks:
string,escape, anddelimhave the type and value of the corresponding arguments of the call to thequotedfunction that constructedproxy.Returns:
is.
The quoted() stream manipulator emerged from discussions on the
Boost developers mailing list. Participants included Beman Dawes, Rob Stewart,
Alexander Lamaison, Eric Niebler, Vicente Botet, Andrey Semashev, Phil Richards,
and Rob Murray. Eric Niebler's suggestions provided the basis for the name and
form of the templates.