Document number:   N3431=12-0121
Date: 2012-09-21
Project: Programming Language C++
Reply-to: Beman Dawes <bdawes at acm dot org>

Quoted Strings Library Proposal

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.

Problem description

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!\""

Proposed Wording

Header <to-be-decided> synopsis

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, const unspecified_typeN& proxy);

Effects: Inserts characters into os:

Remarks: string, escape, and delim have the type and value of the corresponding arguments of the call to the quoted function that constructed proxy.

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, const unspecified_type3& proxy);

Effects: Extracts characters from os:

Remarks: string, escape, and delim have the type and value of the corresponding arguments of the call to the quoted function that constructed proxy.

Returns: is.

Acknowledgements

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.