I was trying to think of a clever way to concatenate various things into a single string argument for a function without having to use an ostringstream explicitly. I thought of:
#define OSS(...) \
dynamic_cast<std::ostringstream const&>(std::ostringstream() << __VA_ARGS__).str()
However, given:
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( OSS( '{' << s << '}' ) );
ostringstream oss;
oss << '{' << s << '}';
cout << oss.str() << endl;
}
it prints when run:
123hello}
{hello}
where 123 is the ASCII code for }. Why does using the macro get it wrong?
FYI: I'm currently using g++ 4.2.1 on Mac OS X as part of Xcode 3.x.
Solution I'm now using
class string_builder {
public:
template<typename T>
string_builder& operator,( T const &t ) {
oss_ << t;
return *this;
}
operator std::string() const {
return oss_.str();
}
private:
std::ostringstream oss_;
};
#define BUILD_STRING(...) (string_builder(), __VA_ARGS__)
using namespace std;
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( BUILD_STRING( '{', s, '}' ) );
}
std::ostringstream() is temporary which thus can be bound only to const references. Standalone operator<< (which take non const references as first argument) aren't considered and only the member one are. The best match in these for a char is converting the char to int.
This problems occurs often with string literals whose address is then displayed.
To solve the problem, the trick is to find a way to transform the temporary in a reference. The member operator<<s do that, but only the one for manipulator does it without side effect and only if the manipulator is a noop -- flush could be used. The members flush and write are also candidates. So for instance
#define OSS(...) \
dynamic_cast<std::ostringstream const&>(std::ostringstream().flush() << __VA_ARGS__).str()
A better thread-safe solution without involving the cumbersome macro.
The original call to function is this:
f( OSS( '{' << s << '}' ) );
How about if the call is just this:
f(stringbuilder() << '{' << s << '}' );
where stringbuilder is implemented as:
struct stringbuilder
{
std::ostringstream ss;
template<typename T>
stringbuilder & operator << (const T &data)
{
ss << data;
return *this;
}
operator string() { return ss.str(); }
};
void f( string const &s ) {
cout << s << endl;
}
Test:
int main() {
char const *const s = "hello";
f(stringbuilder() << '{' << s << '}' );
}
Output:
{hello}
Online Demo : http://ideone.com/QHFf4
Related
I have the following functions
void Assembly::push_back(stringstream& ss){
instructions->push_back(ss.str());
}
std::ostream& pad(std::ostream& os) {
return os <<"\t"<<std::left<< std::setfill(' ') << std::setw(8);
}
where instructions is a list of strings. I want to do sth like
Assembly outfile;
stringstream ss;
outfile.push_back(ss<<pad<<"addiu"<<"$sp, $sp, -8");
but I get an error from the compiler
no known conversion for argument 1 from 'std::basic_ostream<char>' to 'std::stringstream& {aka std::basic_stringstream<char>&}'
I tried changing the definition of push_back to take std::basic_ostream<char> but it still did not compile.
Basically what I want to do is be able to push_back a string which has the alignment that pad adds. It is also essential that I am able to call Assembly::push_back in a single line (I know that
Assembly outfile;
stringstream ss;
ss<<pad<<"addiu"<<"$sp, $sp, -8";
outfile.push_back(ss);
works, but it requires two lines of code to make the proper call). I am also open to solutions which overload the operator<< for Assembly or allow me to accomplish the required behavior in a single line.
Make your pad() take and return a std::stringstream, and then also add this:
template <typename T>
std::stringstream &
operator<<(std::stringstream &ss, const T &o) {
static_cast<std::ostream &>(ss) << o; // Prevent recursion.
return ss;
}
Here is what I think the problem is. This won't work because the return value of ss << anything is always an std::ostream& which is a parent of std::stringstream and does not satisfy the argument for your push_back() function.
void push_back(const std::stringstream& ss)
{
std::cout << "push: " << ss.str() << '\n';
}
int main(int, char* argv[])
{
std::stringstream ss;
// what gets sent to the function is an std::ostream&
// which is an incompatible type.
push_back(ss << "one " << 2 << ' ' << 3.0); // fail
}
The way to fix this is to create an overload for operator<<(std::stringstream& that returns the correct type:
template<typename DataType>
std::stringstream& operator<<(std::stringstream& ss, const DataType& data)
{
static_cast<std::ostream&>(ss) << data;
return ss;
}
Now calling << on a std::stringstream will return a std::stringstream& which is acceptable as your push_back() parameter.
void push_back(const std::stringstream& ss)
{
std::cout << "push: " << ss.str() << '\n';
}
int main(int, char* argv[])
{
std::stringstream ss;
// Now the << returns the correct type (std::stringstream&)
push_back(ss << "one " << 2 << ' ' << 3.0); // good
}
as the title says I am curious if delegation constructor can be called in the body or not.
If you are curious about motivation:
I have some condition and only workaround I found requires having uselss write on dummy member that occupies space.
#include <iostream>
using namespace std;
struct Delegating {
Delegating (const string& str) {
cout <<"const string& \n";
}
Delegating(string&& str): dummy_(str.size()>4 ? 0 : (Delegating(str),0)) {
if (str.size()>4) {
cout <<"string&& \n";
}
}
bool dummy_;
};
int main() {
// your code goes here
Delegating("abc");
Delegating("abcde");
Delegating("abcde");
Delegating("abcde");
Delegating("abc");
cout << "\n--------------------\n";
Delegating(string("abc"));
Delegating(string("abcde"));
Delegating(string("abcde"));
Delegating(string("abcde"));
Delegating(string("abcde"));
Delegating(string("abc"));
return 0;
}
Your code does not do what you think it does. By adding a verbose destructor :
~Delegating() {
std::cout << "~\n";
}
... the output becomes :
const string&
~
~
string&&
~
string&&
~
string&&
~
const string&
~
~
--------------------
(and so on)
Notice there are seven destructor calls, whereas you only instanciated five objects. That's because in the following line :
Delegating(string&& str): dummy_(str.size()>4 ? 0 : (Delegating(str),0)) {
... Delegating(str) is not a delegated constructor call, but an independent temporary object, which is created and destructed during the initialization of dummy_.
The only syntax for delegating constructors is :
Foo(/* params */) : Foo(/* other params */), /* members-init */ {}
// First one ! ^^^^^^^^^^^^^^^^^^^^^^^
... and it is not possible to conditionally delegate. You can resort to a static function that does the check, and returns a suitably-constructed object (a.k.a the "Named Constructor Pattern").
Other answers have already pointed out that you if call a constructor from inside a constructor then you are creating a temporary. I would like to point out that your test cases never call the constructor Delegating (const string& str) directly. In all those cases, Delegating(string && str) is a better fit.
Try the following code that uses named constructors.
#include <iostream>
using namespace std;
struct Delegating
{
Delegating()
{
cout << "default \n";
};
Delegating( const string & str )
{
cout << "const string & \n";
}
Delegating( const string && str )
{
cout << "string && \n";
}
static Delegating constr( const string & a_Str )
{
cout << a_Str.data() << '\t';
return Delegating( a_Str );
}
static Delegating constr( string && x_Str )
{
cout << x_Str.data() << '\t';
if ( x_Str.size() > 4 )
return Delegating();
else
return Delegating( x_Str );
}
~Delegating()
{
cout << "~\n";
}
};
int main()
{
{
Delegating::constr( "abc" );
Delegating::constr( "abcde" );
cout << "\n--------------------\n";
Delegating::constr( string( "abc" ) );
Delegating::constr( string( "abcde" ) );
cout << "\n--------------------\n";
string d_Named( "abc" );
Delegating::constr( d_Named );
d_Named = "abcde";
Delegating::constr( d_Named );
}
return 0;
}
Now I want to write a new version of the following code:
const char * f() {
return "Hello";
}
const char *pf = f();
I wonder how to use reference instead of pointer.
I have one idea by using string.
Is there a more straight way to solve this?
UPDATE:
I read the answer and comments carefully. I got another idea is to treat the return value as a const char array. But this solution seems too complicated and not so clear as a pointer.
If you want to know the syntax then the definition will look the following way
#include <iostream>
const char ( & ( f() ) )[6] { return ( "Hello" ); }
int main()
{
std::cout << f() << std::endl;
}
Or as #Jarod42 advices you can use a typedef that the fiunction definition woild look simpler
#include <iostream>
const char ( & ( f() ) )[6] { return ( "Hello" ); }
typedef const char ( &Array_Ref )[6];
Array_Ref g() { return ( "Hello" ); }
int main()
{
std::cout << f() << std::endl;
std::cout << g() << std::endl;
Array_Ref s = g();
std::cout << s << std::endl;
}
If you want to use std::string then it would be better to write the function as
std::string f() { return ( "Hello" ); }
I've seen some answers to other boost::lexical_cast questions that assert the following is possible:
bool b = boost::lexical_cast< bool >("true");
This doesn't work for me with g++ 4.4.3 boost 1.43. (Maybe it's true that it works on a platform where std::boolalpha is set by default)
This is a nice solution to the string to bool problem but it lacks input validation that boost::lexical_cast provides.
In addition to the answer form poindexter, you can wrap the method from here in a specialized version of boost::lexical_cast:
namespace boost {
template<>
bool lexical_cast<bool, std::string>(const std::string& arg) {
std::istringstream ss(arg);
bool b;
ss >> std::boolalpha >> b;
return b;
}
template<>
std::string lexical_cast<std::string, bool>(const bool& b) {
std::ostringstream ss;
ss << std::boolalpha << b;
return ss.str();
}
}
And use it:
#include <iostream>
#include <boost/lexical_cast.hpp>
//... specializations
int main() {
bool b = boost::lexical_cast<bool>(std::string("true"));
std::cout << std::boolalpha << b << std::endl;
std::string txt = boost::lexical_cast< std::string >(b);
std::cout << txt << std::endl;
return 0;
}
I personally liked this approach because it hides any special code (e.g. using LocaleBool or to_bool(...) from the link) for converting to/from bools.
I'm posting the answer to my own question here for others who may be looking for something like this:
struct LocaleBool {
bool data;
LocaleBool() {}
LocaleBool( bool data ) : data(data) {}
operator bool() const { return data; }
friend std::ostream & operator << ( std::ostream &out, LocaleBool b ) {
out << std::boolalpha << b.data;
return out;
}
friend std::istream & operator >> ( std::istream &in, LocaleBool &b ) {
in >> std::boolalpha >> b.data;
return in;
}
};
usage:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include "LocaleBool.hpp"
int main() {
bool b = boost::lexical_cast< LocaleBool >("true");
std::cout << std::boolalpha << b << std::endl;
std::string txt = boost::lexical_cast< std::string >( LocaleBool( b ) );
std::cout << txt << std::endl;
return 0;
}
Put together your own template on top of boost lexical cast for parsing. Note the "default" parameter in the example to ensure overloading works correctly (feel free to use another means if you want).
template<typename T>
T Parse(const std::string& valStr, const T& default=T()) {
T result = boost::lexical_cast<T>(valStr);
}
Then, you can specialize for ANYTHING, including bools:
template<>
bool Parse(const std::string& valStr, const bool& default=true) {
if(strcmp(valStr.c_str(), "true") == 0) {
return true;
}
return false;
}
Obviously there are a number of ways to do this, and you can add more conditions for true vs false (I'd make sure all variants of "TRUE" and "FALSE" like "True", plus "T" and "F" work right). You could even extend it to numeric parsing.
I've seen some answers to other boost::lexical_cast questions that assert the following is possible:
bool b = boost::lexical_cast< bool >("true");
This doesn't work for me with g++ 4.4.3 boost 1.43. (Maybe it's true that it works on a platform where std::boolalpha is set by default)
This is a nice solution to the string to bool problem but it lacks input validation that boost::lexical_cast provides.
In addition to the answer form poindexter, you can wrap the method from here in a specialized version of boost::lexical_cast:
namespace boost {
template<>
bool lexical_cast<bool, std::string>(const std::string& arg) {
std::istringstream ss(arg);
bool b;
ss >> std::boolalpha >> b;
return b;
}
template<>
std::string lexical_cast<std::string, bool>(const bool& b) {
std::ostringstream ss;
ss << std::boolalpha << b;
return ss.str();
}
}
And use it:
#include <iostream>
#include <boost/lexical_cast.hpp>
//... specializations
int main() {
bool b = boost::lexical_cast<bool>(std::string("true"));
std::cout << std::boolalpha << b << std::endl;
std::string txt = boost::lexical_cast< std::string >(b);
std::cout << txt << std::endl;
return 0;
}
I personally liked this approach because it hides any special code (e.g. using LocaleBool or to_bool(...) from the link) for converting to/from bools.
I'm posting the answer to my own question here for others who may be looking for something like this:
struct LocaleBool {
bool data;
LocaleBool() {}
LocaleBool( bool data ) : data(data) {}
operator bool() const { return data; }
friend std::ostream & operator << ( std::ostream &out, LocaleBool b ) {
out << std::boolalpha << b.data;
return out;
}
friend std::istream & operator >> ( std::istream &in, LocaleBool &b ) {
in >> std::boolalpha >> b.data;
return in;
}
};
usage:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include "LocaleBool.hpp"
int main() {
bool b = boost::lexical_cast< LocaleBool >("true");
std::cout << std::boolalpha << b << std::endl;
std::string txt = boost::lexical_cast< std::string >( LocaleBool( b ) );
std::cout << txt << std::endl;
return 0;
}
Put together your own template on top of boost lexical cast for parsing. Note the "default" parameter in the example to ensure overloading works correctly (feel free to use another means if you want).
template<typename T>
T Parse(const std::string& valStr, const T& default=T()) {
T result = boost::lexical_cast<T>(valStr);
}
Then, you can specialize for ANYTHING, including bools:
template<>
bool Parse(const std::string& valStr, const bool& default=true) {
if(strcmp(valStr.c_str(), "true") == 0) {
return true;
}
return false;
}
Obviously there are a number of ways to do this, and you can add more conditions for true vs false (I'd make sure all variants of "TRUE" and "FALSE" like "True", plus "T" and "F" work right). You could even extend it to numeric parsing.