// demo_string.h
#ifndef INCLUDED_STRING
#define INCLUDED_STRING
#include <iosfwd>
#include <string>
namespace demo
{
// The class string is merely defined to have something which can be used
// to overload the output operator.
struct string
: std::string {
using std::string::string;
};
std::ostream& operator<< (std::ostream&, string const&);
std::ostream& noquote(std::ostream&);
std::ostream& squote(std::ostream&);
std::ostream& dquote(std::ostream&);
struct prefix
: std::string {
using std::string::string;
};
std::ostream& operator<< (std::ostream&, prefix const&);
}
#endif
// demo_string.cpp
// #include "demo/string.h"
#include <ostream>
namespace
{
int stringFormatIndex() {
static int rc = std::ios_base::xalloc();
return rc;
}
void callback(std::ios_base::event ev, std::ios_base& s, int index) {
void* pword = s.pword(index);
switch (ev) {
case std::ios_base::erase_event:
delete static_cast<std::string*>(pword);
pword = 0;
break;
case std::ios_base::copyfmt_event:
pword = new std::string(*static_cast<std::string*>(pword));
break;
default:
break;
}
}
}
std::ostream& demo::noquote(std::ostream& out) {
out.iword(stringFormatIndex()) = 0;
return out;
}
std::ostream& demo::squote(std::ostream& out) {
out.iword(stringFormatIndex()) = '\'';
return out;
}
std::ostream& demo::dquote(std::ostream& out) {
out.iword(stringFormatIndex()) = '"';
return out;
}
std::ostream& demo::operator<< (std::ostream& out, demo::string const& str) {
int index{stringFormatIndex()};
if (out.pword(index)) {
out << *static_cast<std::string const*>(out.pword(index));
}
char quote(out.iword(index));
return quote? out << quote << str.c_str() << quote: out << str.c_str();
}
std::ostream& demo::operator<< (std::ostream& out, demo::prefix const& p) {
void*& pword(out.pword(stringFormatIndex()));
if (pword) {
*static_cast<std::string*>(pword) = p;
}
else {
out.register_callback(&callback, stringFormatIndex());
pword = new std::string(p);
}
return out;
}
// main.cpp
// #include "demo/string.h"
#include <iostream>
int main()
{
demo::string value("whatever");
std::cout << demo::prefix("value=")
<< value << ' '
<< demo::squote << value << ' '
<< demo::dquote << value << ' '
<< demo::noquote << value << ' '
<< '\n';
;
}