std::stringstream "str" returning nothing? - c++

I'm having trouble with std::stringstream. My function as seen below returns absolutely nothing. Even when trying a stringstream outside of the template function it still returns nothing when .str() is called.
template < class T > std::string toString( const T &t )
{
std::stringstream temp;
temp << t;
std::cout << temp.str() << std::endl;
return temp.str();
}
std::string test = "test" + toString( 1 );
std::cout << test << std::endl;
std::stringstream stream;
stream << "test" << 1;
std::cout << stream.str() << std::endl;
Both of these output only "test"
Fixed
Had to remove _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC from my preprocessor macros.

Try ostringstream instead of stringstream.
== UPDATE ==
I compiled your code with GCC 4.6.1, and it works as-is:
#include <iostream>
#include <sstream>
using namespace std;
template < class T > std::string toString( const T &t )
{
std::stringstream temp;
temp << t;
std::cout << temp.str() << std::endl;
return temp.str();
}
int main()
{
std::string test = "test" + toString( 1 );
std::cout << test << std::endl;
std::stringstream stream;
stream << "test" << 1;
std::cout << stream.str() << std::endl;
return 0;
}
Output:
1
test1
test1

#include <iostream>
#include <sstream>
#include <string>
template < class T > std::string toString( const T &t )
{
std::stringstream temp;
temp << t;
std::cout << temp.str() << std::endl;
return temp.str();
}
int main(){
std::string test = "test" + toString( 1 );
std::cout << test << std::endl;
std::stringstream stream;
stream << "test" << 1;
std::cout << stream.str() << std::endl;
}
Outputs
1
test1
test1
For me with Clang 3.1, GCC 4.4.5 and MSVC 10, so your problem lies elsewhere. Please try just the code above in a new project and see if the problem persists. If not, the suggestions by #Industrial-antidepressant sounds quite realistic, i.e. that you have a better matching overload lying around somewhere.

Related

C++ stringstream question, how can I make each line seperate

I'm sorry the title may be inaccurate.I'm new to C++.
Here is my code and output...
#include <iostream>
#include <sstream>
using namespace std;
class LogLine {
private:
stringstream ss;
string message;
public:
~LogLine() {
ss << "\n";
message = ss.str();
cout << message;
message = "";
}
template <class T>
LogLine& operator<<(const T& thing) {
ss<< thing;
return *this;
}
LogLine& operator<<(std::ostream &(*manip)(std::ostream &)) {
manip(ss);
return *this;
}
};
int main(int argc, char *argv[])
{
LogLine log;
cout<< "Line One"<<endl;
log << "I'm " << 25 << " years old...."<<endl;
cout<<"Line Two"<<endl;
log << "I " << "Live in " << " Houston....";
return 0;
}
Current output:
Line One
Line Two
I'm 25 years old....
I Live in Houston....
Desired output:
Line One
I'm 25 years old....
Line Two
I Live in Houston....
I hope in each line of "log" be able to detect the end of that line and print out current message, and then clean itself. I know the reason of current output, but I can't figure out how should I modify my code to get desired output.("endl" can be missing)
Thanks a lot for any comments.
As described above...
When I understand you correctly, you want to detect the end of the statement, where log is used, and then append a std::endl.
My solution is similar to that one of #MarekR, but it forces a line break, when log is not rebound:
It does not detect "\n" and flushes it to std::cout, that would be contra productive on parallel std::cout calls.
#include <iostream>
#include <sstream>
using std::cout;
using std::endl;
class LogLine {
std::stringstream ss;
public:
LogLine(LogLine&&) noexcept = default;
LogLine() = default;
~LogLine()
{
if(ss && ss.peek() != -1){
cout << ss.str() << std::endl;
}
}
template <class T>
friend LogLine operator<<(LogLine& lhs, const T& thing)
{
lhs.ss << thing;
return std::move(lhs);
}
template <class T>
friend LogLine&& operator<<(LogLine && lhs, const T& thing)
{
lhs.ss << thing;
return std::move(lhs);
}
LogLine&& operator<<(std::ostream& (*manip)(std::ostream&))
{
manip(ss);
return std::move(*this);
}
};
int main()
{
LogLine forced;
cout << "Line One" << endl;
forced << "I'm " << 25 << " years old....";
cout << "Line Two" << endl;
LogLine() << "I " << "Live in " << " Houston...." << endl << endl << endl;
forced << "forced 2";
std::cout << "End of the sausage" << std::endl;
return 0;
}
That what happens here is: every call to operator<< creates a temporary, which steals the resources of the original structure. Therefore, when it is not rebound, the destructor gets called directly after the line, flushing the stringstream.

std::move(std::string) not making passed argument to empty state

I'm bit confused why the std::move(std::string) not making the passed std::string argument to an empty state (I mean std::string size as 0 and its internal buffer to point to nullptr after call to std::move(std::string)). This is a sample code
#include <iostream>
#include <string>
void print(std::string& str) {
std::cout << "lref\n";
std::cout << str << "\n" << std::endl;
}
void print(const std::string& str) {
std::cout << "const lref\n";
std::cout << str << "\n" << std::endl;
}
void print(std::string&& str) {
std::cout << "rref\n";
std::cout << str << "\n" << std::endl;
}
int main() {
std::string str_a = "Hello, ";
std::string str_b = "world!";
print(str_a);
print(str_b);
print(str_a + str_b);
print(std::move(str_a));
print(str_a); // was expecting str_a to be empty but still prints Hello,
return 0;
}
std::move is not moving anything. It cast its argument to an rvalue-reference. To actually move you need to pass str as rvalue-reference to move constructor(or move assignment) of another string as below.
std::string new_str(std::move(str));
print(str);

C++ / Boost:: Propery_Tree - Is it possible to take ini config value with dot in name [duplicate]

"A": "1"
"A.B": "2"
"A.C": "3"
How to get the value of A.B if i iterate through the ptree it works. if i try
to get value of pt.get_child("A\.B").get_value<std::string>(). i get the following exception
terminate called after throwing an instance of boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::property_tree::ptree_bad_path> >'
what(): No such node
please find the complete code below
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <iostream>
#include <string>
#include <iterator>
using boost::property_tree::ptree;
/* Indent Json Output */
std::string indent(int level) {
std::string s;
for (int i = 0; i < level; i++) s += " ";
return s;
}
/* Print tree in json format */
void printTree(ptree & pt, int level) {
if (pt.empty()) {
std::cerr << "\"" << pt.data() << "\"";
} else {
if (level) std::cerr << std::endl;
std::cerr << indent(level) << "{" << std::endl;
for (ptree::iterator pos = pt.begin(); pos != pt.end();) {
std::cerr << indent(level + 1) << "\"" << pos-> first << "\": ";
printTree(pos->second, level + 1);
++pos;
if (pos != pt.end()) {
std::cerr << ",";
}
std::cerr << std::endl;
}
std::cerr << indent(level) << " }";
}
return;
}
int main()
{
ptree pt;
read_ini("sample.ini", pt);
printTree(pt, 0);
std::cout << pt.get_child("A.B").get_value<std::string>() << std::endl; //tries to resolve A.B to two nodes
std::cout << pt.get_child("A\\.B").get_value<std::string>() << std::endl; //error
}
sample.ini
A=1
A.B=2
A.C=3
You can use alternative path delimiters, but it's a bit tricky and not very well documented.
You have to temporarily specify an alternative path separator:
Live On Coliru
#include <boost/property_tree/ini_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
int main() {
ptree pt;
pt.put("a.b", "first");
pt.put(ptree::path_type("a|complicated.name", '|'), "second");
write_ini(std::cout, pt);
}
Prints
[a]
b=first
complicated.name=second

std::stringstream to return char *

This is my code:
#include <iostream>
#include <sstream>
void serialize(std::ostream& os)
{
int r1 = 10;
int r2 = 12;
os.write(reinterpret_cast<char const*>(&r1), sizeof(r1));
os.write(reinterpret_cast<char const*>(&r2), sizeof(r2));
}
int main()
{
std::stringstream ss;
serialize(ss);
std::cout<<" Buffer length : " << ss.str().length() <<'\n'; //This print correct length
const char *ptrToBuff = ss.str().c_str();// HERE is the problem. char * does not contain anything.
std::cout <<ptrToBuff; // NOTHING is printed
}
How to get a char pointer to the stream buffer?
The problem is std::cout << ptrToBuff; does not print anything
A pointer to the stream will leave a dangling pointer, you can copy the string though:
const std::string s = ss.str();
And then point your const char* to it:
const char *ptrToBuff = s.c_str();
In your serialize function you should use << operator to write to ostream:
os << r1 << " " << sizeof(r1) << std::endl;
os << r2 << " " << sizeof(r2) << std::endl;
So the whole code will be: (see here)
void serialize(std::ostream& os)
{
int r1 = 10;
int r2 = 12;
os << r1 << " " << sizeof(r1) << std::endl;
os << r2 << " " << sizeof(r2) << std::endl;
}
int main()
{
std::stringstream ss;
serialize(ss);
std::cout<<"Buffer length : " << ss.str().length() <<'\n';
const std::string s = ss.str();
const char *ptrToBuff = s.c_str();
std::cout << ptrToBuff;
}

boost::variant gives wrong result when bool appears as possible type

The code that works is the following:
#include <boost/variant.hpp>
#include <string>
#include <map>
#include <iostream>
int main(int argc, char** argv) {
std::map<std::string, boost::variant<int, std::string> > values;
values["a"] = 10;
values["b"] = "bstring";
values["c"] = "cstring";
for (const auto &p : values) {
std::cout << p.first << " = ";
if (p.second.type() == typeid(std::string)) {
std::cout << boost::get<std::string>( p.second ) << " (found string)" << std::endl;
} else if ( p.second.type() == typeid(int)) {
std::cout << boost::get<int>( p.second ) << " (found int)" << std::endl;
} else if ( p.second.type() == typeid(bool)) {
std::cout << boost::get<bool>( p.second ) << " (found bool)" << std::endl;
} else {
std::cout << " not supported type " << std::endl;
}
}
}
The output (g++ test.cpp -std=c++11):
a = 10
b = bstring
c = cstring
The code that does not work is exactly the same, except the line that defines the std::map
modifying the line of the map definition to:
std::map<std::string, boost::variant<int, std::string, bool> > values;
the output is different:
a = 10
b = c =
The if statement that refers to std::string comparison does not succeed. What is the problem?
In your code, values["b"] = "bstring"; creates a bool value, when both std::string and bool are in the variant type.
A fix is values["b"] = std::string("bstring");.
Or, in C++14:
using namespace std::string_literals;
values["b"] = "bstring"s;
It is a well-known annoyance that string literals better convert to bool than to std::string:
#include <iostream>
#include <string>
void f(std::string) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
void f(std::string const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
void f(bool) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
int main() {
f("hello");
}
Outputs:
void f(bool)