#include <string>
#include <iostream>

/** string concatenation helper widget see test below for usage */
class concat
{
public:

	concat ()
		: totsize (0), prev (0), pstr (0)
	{ }

	operator std::string()
	{
		std::string s;
		s << *this;
		return s;
	}

private:

	friend concat operator+ (const concat &, const std::string &);

	friend void operator<< (std::string &, const concat &);

	concat (const concat & n, size_t ts, const std::string & s)
		: totsize (ts), prev (&n), pstr (&s)
	{ }

	const concat      * prev;
	const std::string * pstr;
	size_t              totsize;
};

concat operator+ (const concat & x, const std::string & s)
{
	return concat (x, x.totsize + s.size (), s);
}

void operator<< (std::string & dest, const concat & cc)
{
	dest.resize (cc.totsize);

	std::string::reverse_iterator dest_rit = dest.rbegin ();

	for (const concat * pcc = &cc; pcc && pcc->pstr; pcc = pcc->prev)
	{
		const std::string & cc_str = *(pcc->pstr);

		std::string::const_reverse_iterator rit = cc_str.rbegin ();
		std::string::const_reverse_iterator ren = cc_str.rend ();

		for ( ; rit != ren; ++rit, ++dest_rit)
			*dest_rit = *rit;
	}
}

int main (int argc, char ** argv)
{
	std::string a = "foo ";
	std::string b = "barbell ";
	std::string c = "bax";
	
	std::string s1;
	
	// using shift operator
	s1 << concat () + a + b + c;
	std::cerr << "s1 is '" << s1 << "'\n";

	// using assingment
	std::string s2 = concat () + a + b + c;
	std::cerr << "s2 is '" << s2 << "'\n";

	// usual method
	std::string s3;
	s3  = a;
	s3 += b;
	s3 += c;
	std::cerr << "s3 is '" << s3 << "'\n";

	// hand optimized for allocation reduction
	std::string s4;
	s4.reserve (a.size () + b.size () + c.size ());
	s4  = a;
	s4 += b;
	s4 += c;
	std::cerr << "s4 is '" << s4 << "'\n";

	return 0;
}

