I am attempting to use an overloaded function to get a string.
void get(char prompt[], int size,const std::string b = "")
{
std::cout << prompt << ": ";
std::cin.get(b, size);
std::cin.ignore(10, '\n');
}
Now I did just change the last argument from a character array to a string at the advice of another poster on this site, so I'm a little lost. I'm getting error message at the '.' in between cin and get. I've also tried cin.getline (I have no idea if there's a difference or what it is)
Error message : cannot convert parameter 1 from 'const std::string' to
'char *'
The error has a lot of other stuff, but I think that's the important bit.
I'm indirectly answering your question by suggesting an alternative method. Here's my implementation, along with an example of how to use it.
#include <string>
#include <iostream>
#include <ostream>
std::string get(std::string const& prompt)
{
std::string ret;
std::cout << prompt << ": ";
getline(std::cin, ret);
return ret;
}
int main()
{
std::cout << get("Please enter your answer") << std::endl;
// or
std::string prompt("Enter your answer");
std::string response = get(prompt);
std::cout << response << std::endl;
}
When working with strings, you need to use the free function getline from the string header, not the member function getline from iostream. So it would be std::getline(std::cin, b);.
That being said getline won't accept a const string as its argument for the simple reason that the whole point of calling getline is to write to the string. Also note that unless you make b a (non-const) reference, any changes you perform on b inside your get method will not be visible outside of the method since strings are copied if you pass them by value.
The difference between istream::get(char*, streamsize) and istream::getline(char*, streamsize) is that the latter discards the newline character (as does the getline method for strings) while the former does not.
http://www.cplusplus.com/reference/iostream/istream/get/
http://www.cplusplus.com/reference/iostream/istream/ignore/
your call to get() doesn't match any of the existing istream methods. it just may end up being recursive if it ever works?
#include <string>
namespace std {
//I am attempting to use an overloaded function to get a string.
class Ciostream : public iostream {
public:
void get(char prompt[], int size,const std::string b = "")
{
cout << prompt << ": ";
cin.get(b, size);
cin.ignore(10, '\n');
}
};
}
//1.cpp:11:28: error: no matching function for call to 'std::basic_istream<char>::get(const string&, int&)'
Related
I have written a simple C++ program to accept a callback.
What callback does? the callback is the second argument of the main function and it simply returns a string, that string is then inserted into a .txt file by main function.
What is the error? Visual studio 2013 throws this error:
error C2664: 'void WriteToFile(std::string,std::string (__cdecl *)(std::string))' : cannot convert argument 2 from 'std::string' to 'std::string (__cdecl *)(std::string)'
Here is the code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void WriteToFile(string filename, string (*f)(string) )
{
ofstream FileProcessor;
FileProcessor.open(filename, ios::app);
FileProcessor << &f << endl;
}
string Printer(string Content)
{
return Content;
}
int main()
{
WriteToFile("test.txt", Printer("exampleText"));
}
AFAIK Printer("exampleText") is passed incorrectly. The second argument of function WriteToFile accepts a pointer to function. So just pass the function Printer.
The argument for the passed function pointer should be sent as different argument.
Something like-
void WriteToFile(string filename, string (*f)(string), string mystring )
{
ofstream FileProcessor;
FileProcessor.open(filename, ios::app);
FileProcessor << f(mystring) << endl;
}
and then called like
WriteToFile("test.txt", Printer, "exampleText");
WriteToFile is expecting the second argument to be a function pointer, not the result of a function call. Change the call to look like this:
WriteToFile("test.txt", Printer);
Still, it doesn't make much sense, because &f is the address of the function, so it'll just print some hex value. You probably want to call the function pointer:
FileProcessor << (*f)("exampleText") << endl;
For passing the argument, you have two options. Vinayak Garg listed one, which is to add a third argument to WriteToFile. The other one is to use std::bind.
WriteToFile("test.txt", std::bind(&Printer, "exampleText"));
In the latter case it will not look like it takes an argument however. Your definition of WriteToFile should look like this (untested):
void WriteToFile(string filename, const std::function<string()> &f )
{
...
FileProcessor << f() << endl;
}
For a project, I'd like to use stringstream to carry on data. To achieve this goal, I have to pass some stringstream as parameter to some function, but when I output the stringstreams, I see something like an address.
The code :
#include <iostream>
#include <sstream>
void doStuff(const std::iostream& msg)
{
std::cerr << msg << std::endl;
}
int main(void)
{
doStuff(std::stringstream("av"));
}
The output is :
0xbff4eb40
Can someone explains why I get an address when passing an rvalue ?
And why can't I pass a stringstream by value ?
You probably want to access the string on which the stringstream is storing its data:
void doStuff(const std::stringstream& msg)
{
std::cerr << msg.str() << std::endl;
}
What is happening in your code is that iostreams contain a void* operator which returns 0 if the stream contains any error or has reached EOF, and another value otherwise. This is usefull for error checking.
When you try to write you stream to std::cerr, the compiler realizes that the stream can be converted to a void* using that operator, and that a void* can be written to a ostream(the operator<< has been defined), and therefore uses it.
Note that i changed the method's signature so that it receives an std::stringstream as an argument, since std::iostream::str is not defined(this method is only available on string streams).
You get an address because it (like other streams) has a conversion to void * (which is primarily useful as a Boolean, to see whether reading/writing the stream has failed).
You can't pass it by value, because streams (again, in general, not just stringstreams) don't support copying and/or assigning.
To print the content of the stream, you could do something like:
void dostuff(std::iostream &msg) {
std::cerr << msg.rdbuf() << "\n";
}
Edit: Here's a complete demo program:
#include <iostream>
#include <sstream>
void show(std::ostream &os) {
std::cout << os.rdbuf() << "\n";
}
int main(){
std::stringstream test("whatever");
show(test);
return 0;
}
When I execute it, the output I get is the expected "whatever".
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Printing a string to a temporary stream object in C++
std::ostringstream printing the address of the c-string instead of its content
I'm trying to build up a string using stringstream, in the same way you'd use cout. This for something like a logging class. The issue I'm having is that if the first argument to the << operator is a string, when I subsequently print out that stringstream with the stringstream::str() call, I get a garbage address, and not the string. This only occurs with the FIRST string. Subsequent strings are fine. Numbers are always fine. Here's the code:
// class I use to print out the stream
class StreamWriter
{
public:
StreamWriter()
{}
~StreamWriter()
{
std::string myMessage = m_stringstream.str();
std::cout << myMessage << std::endl;
}
std::stringstream m_stringstream;
};
// macro for simplification
#define OSRDEBUG (StreamWriter().m_stringstream)
// actual use
OSRDEBUG << "Hello " << "my " << "name is Pris " << 123456;
// output
0x8054480my name is Pris 123456
0x8054480my name is Pris 123456
0x8054480my name is Pris 123456
0x8054480my name is Pris 123456
Could anyone shed some light on what's going on, and how I could get around the issue?
EDIT:
The following changes (in addition to padiablo's examples) works as well, maintaining the use of the class's destructor with the macro.
// class I use to print out the stream
class StreamWriter
{
public:
StreamWriter()
{ m_stringstream = new std::stringstream; }
~StreamWriter()
{
std::string myMessage = m_stringstream.str();
std::cout << myMessage << std::endl;
delete m_stringstream;
}
std::stringstream * m_stringstream;
};
// macro for simplication
#define OSRDEBUG *(StreamWriter().m_stringstream)
The original question still stands though, because it looks like it should work... and I think it's probably important to know when the times comes to put this into production-quality code.
The problem is indeed that the stream is a temporary.
Before C++11, there was no non-member operator<< overload that took an rvalue reference as the first parameter (aka, allowing writes to temporary streams).
As such, the only valid operator<< overloads were the members, since all non-member overloads take a non-const reference and as such will not bind to temporaries. One of those non-member overloads is the one responsible for printing C strings (aka char const*). Here's one of the member overloads:
basic_ostream<Ch, Traits>& operator<<(void* p);
And guess what your string literal liberally converts to. :)
After the first string, you get a normal reference back from the call to operator<<, which will then allow the non-member overloads to be viable.
I honestly don't understand exactly what's going on (it has something to do with your StreamWriter instance being a temporary), but I see the same effect as paxdiablo described in both GCC and MSVC.
However, here's something that can work around the problem. Add the following helper to your StreamWriter class:
ostream& get_ostream() {
return m_stringstream;
}
and change the macro to:
#define OSRDEBUG (StreamWriter().get_ostream())
I have tried a couple of alternatives, and the only thing I got working is something like this:
#define OSRDEBUG(s) \
do \
{ \
StreamWriter writer; \
writer.m_stringstream << s; \
} while (0)
OSRDEBUG("Hello " << "my " << "name is Pris " << 123456);
I have personally used the above construct for my own logging solutions many times, and seen it done by others as well.
I'm not good enough to know why your example doesn't work, but I guess it has something to do with temporaries not staying alive long enough.
It appears to be a consequence of the way you're instantiating the object. I'm still investigating (and you may get a better answer in the meantime) but explicitly instantiating the object works fine:
#include <iostream>
#include <sstream>
class StreamWriter {
public:
StreamWriter() {}
~StreamWriter() { std::cout << m_stringstream.str() << std::endl; }
std::stringstream m_stringstream;
};
int main (void) {
StreamWriter *sw = new StreamWriter();
sw->m_stringstream << "Hello " << "my " << "name is Pris ";
delete sw;
return 0;
}
As does instantiating on the stack as well:
int main (void) {
StreamWriter sw;
sw.m_stringstream << "Hello " << "my " << "name is Pris ";
return 0;
}
Both of those print out what you expect but the following simplification of your code does not:
int main (void) {
StreamWriter().m_stringstream << "Hello " << "my " << "name is Pris ";
return 0;
}
If you're just after a solution, you can probably get by with:
#define ORSDEBUG StreamWriter sw; sw.m_stringstream
and ensuring you scope-protect the command so that it doesn't try to create more then one sw, and also that it's destroyed at the correct time, same as your original attempt:
{ ORSDEBUG << "Hello " << "my " << "name is Pris"; }
What I mean:
Everyone knows this method of redirecting stream to output:
cout << "sometext"
but is it possible to pass that stream to a function like this:
my_function() << "sometext";
Yes*:
#include <iostream>
#include <ostream>
std::ostream & my_function() { return std::cout; }
// ...
my_function() << "Hello world.\n";
*) Nothing you said in words is entirely correct, and you may well struggle later integrate this into your project, but this answer shows how to make your code do what you want.
Everyone knows this method of redirecting stream to output:
That's not what that does. The stream is called cout; that's the iostream object. The << operator does not redirect anything. The std::ostream objects all have overloaded operator<< functions. Those functions are invoked when you use << with a stream on the left-hand side and some type that has an overload for it on the right.
<< "sometext" is not a "stream" that can be "redirected". It isn't even a valid expression in C++. The << operator is binary. it takes two parameters.
my_function() << "sometext"; can only work if it returns a std::ostream class or something derived from it. Or something that has an overloaded operator<< defined for it and const char*.
cout << "sometext"
This is not "redirecting stream to output" it is invoking the operator << function on the cout object with the string literal "sometext"
if my_function() is returning a ostream which has operator << overloaded then my_function() << "sometext" will compile else it will give an error.
If you are looking for a way to overload << for your own function unrelated to streams, here is how you can do it:
struct MyStruct {
void DoSomething(const string& s);
};
MyStruct &operator<<(MyStruct &x, const string& s) {
x.DoSomething(s);
return x;
}
MyStruct& my_function() {
return MyStruct;
}
int main() {
my_function() << "Hello, world!";
}
In this example, DoSomething will be called on the instance of MyStruct returned from my_function, and "Hello, world!" will be passed to it as an argument.
If I understand what you are asking about, the closest equivalent of a shell redirect for a function that uses std::cout for output is probably to switch temporarily std::cout's internal stream buffer for a different one.
Of course, this is inherently not thread safe and won't cope if the function itself expects std::cout and stdout to be the same underlying thing.
#include <iostream>
#include <sstream>
int main()
{
std::stringbuf redir( std::ios_base::out );
std::streambuf* save = std::cout.rdbuf( &redir );
my_function(); // cout output ends up in redir
std::cout.rdbuf( save ); // restore original cout
}
void outputString(const string &ss) {
cout << "outputString(const string& ) " + ss << endl;
}
void outputString(const string ss) {
cout << "outputString(const string ) " + ss << endl;
}
int main(void) {
//! outputString("ambigiousmethod");
const string constStr = "ambigiousmethod2";
//! outputString(constStr);
} ///:~
How to make distinct call?
EDIT: This piece of code could be compiled with g++ and MSVC.
thanks.
C++ does not allow you to overload functions where the only difference in the function signature is that one takes an object and another takes reference to an object. So something like:
void foo(int);
and
void foo(int&);
is not allowed.
You need to change the number and/or the type of the parameter.
In your case the function that accepts a reference, you can make it accept a pointer, if you want to allow the function to change its argument.
You could change the signature of one of the methods. It may not look pretty, however it is the simplest way.
So you could in principle have
void outputString(const string &ss, int notneeded) {
cout << "outputString(const string& ) " + ss << endl;
}
void outputString(const string ss) {
cout << "outputString(const string ) " + ss << endl;
}
and when you want to call the first function just call it with:
outputString("ambigiousmethod", 0);
which will result in a distinguishing call.
There is no other way (I'd love to be proven wrong on this one) since C++ does not allow overloading where passing (by value or by reference) is the only difference in signature.
Edit: as pointed out by bzabhi, you could also change the signature by changing the reference to a pointer. In the example you gave that would work, however you may have to change function code on some occasions.
According to your code, u need only
void outputString(const string &ss).
Because both methods cannot change the argument to the caller (because it's const reference or by-value passing).
Why do you need those 2 methods?
I recommend using the techinque of giving each and every function a unique name., i.e., do not use syntax overloading. I have been using it for years and I've only found advantages in it.