#include <iostream>
using namespace std;
struct info {
info(int x, int y) : x(x), y(y) {}
int x;
int y;
};
ostream& operator<<(ostream& out, const info &myinfo){
out << myinfo.x << " " << myinfo.y;
return cout;
}
int main() {
info a(1,2);
info b(3,4);
cout << a << " " << b << endl;
}
The output of the above program seems fine even with the incorrect overload of operator <<.
Can anyone tell me what is the effect of this overloading problem? I know the overloading function should return out instead of cout, but how does the above version behave?
In this case, since you are passing in std::cout to the overloaded operator<<, there is no difference in behavior. Generally, though, you would cause the " " << b << std::endl to get sent to std:cout, while your a would go to whatever you passed in.
For example:
info a(1,2);
info b(3,4);
std::ostringstream ss;
ss << a << " " << b << std::endl;
would cause a to go to ss.
It will work in this situation, obviously, because the target stream is cout. It will break in other situations.
It just happens to work here, because out and cout refers to the same object.
Related
I am trying to overload
<<
operator. For instance
cout << a << " " << b << " "; // I am not allowed to change this line
is given I have to print it in format
<literal_valueof_a><"\n>
<literal_valueof_b><"\n">
<"\n">
I tried to overload << operator giving string as argument but it is not working. So I guess literal
" "
is not a string. If it is not then what is it. And how to overload it?
Kindly help;
Full code
//Begin Program
// Begin -> Non - Editable
#include <iostream>
#include <string>
using namespace std;
// End -> Non -Editable
//---------------------------------------------------------------------
// Begin -> Editable (I have written )
ostream& operator << (ostream& os, const string& str) {
string s = " ";
if(str == " ") {
os << '\n';
}
else {
for(int i = 0; i < str.length(); ++i)
os << str[i];
}
return os;
}
// End -> Editable
//--------------------------------------------------------------------------
// Begin -> No-Editable
int main() {
int a, b;
double s, t;
string mr, ms;
cin >> a >> b >> s >> t ;
cin >> mr >> ms ;
cout << a << " " << b << " " ;
cout << s << " " << t << " " ;
cout << mr << " " << ms ;
return 0;
}
// End -> Non-Editable
//End Program
Inputs and outputs
Input
30 20 5.6 2.3 hello world
Output
30
20
5.6
2.3
hello
world
" " is a string-literal of length one, and thus has type const char[2]. std::string is not related.
Theoretically, you could thus overload it as:
auto& operator<<(std::ostream& os, const char (&s)[2]) {
return os << (*s == ' ' && !s[1] ? +"\n" : +s);
}
While that trumps all the other overloads, now things get really hairy. The problem is that some_ostream << " " is likely not uncommon, even in templates, and now no longer resolves to calling the standard function. Those templates now have a different definition in the affected translation-units than in non-affected ones, thus violating the one-definition-rule.
What you should do, is not try to apply a global solution to a very local problem:
Preferably, modify your code currently streaming the space-character.
Alternatively, write your own stream-buffer which translates it as you wish, into newline.
Sure this is possible, as I have tested. It should be portable since you are specifying an override of a templated function operator<<() included from <iostream>. The " " string in your code is not a std::string, but rather a C-style string (i.e. a const char *). The following definition works correctly:
ostream& operator << (ostream& os, const char *str) {
if(strcmp(str, " ") == 0) {
os << '\n';
} else {
// Call the standard library implementation
operator<< < std::char_traits<char> > (os, str);
}
return os;
}
Note that the space after std::char_traits<char> is necessary only if you are pre-c++11.
Edit 1
I agree with Deduplicator that this is a potentially dangerous solution as it may cause undesirable consequences elsewhere in the code base. If it is needed only in the current file, you could make it a static function (by putting it within an unnamed namespace). Perhaps if you shared more about the specifics of your problem, we could come up with a cleaner solution for you.
You might want to go with a user defined literal, e.g.
struct NewLine {};
std::ostream& operator << (std::ostream& os, NewLine)
{
return os << "\n";
}
NewLine operator ""_nl(const char*, std::size_t) // "nl" for newline
{
return {};
}
This can be used as follows.
int main(int, char **)
{
std::cout << 42 << ""_nl << "43" << ""_nl;
return 0;
}
Note three things here:
You can pass any string literal followed by the literal identifier, ""_nl does the same thing as " "_nl or "hello, world"_nl. You can change this by adjusting the function returning the NewLine object.
This solution is more of an awkward and confusing hack. The only real use case I can imagine is pertaining the option to easily change the behavior at a later point in time.
When doing something non-standard, it's best to make that obvious and explicit - here, the user defined literal indeed shines, because << ""_nl is more likely to catch readers' attention than << " ".
I have a method to log with the following definition:
void log(std::string s) {
std::string tag = "main";
std::cout << tag << " :" << s << std::endl;
}
I'm trying to call this method like this:
log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
direction and count are integers.
I'm getting this following error with << underlined in red:
no operator << matches these operands.
operand types are const char [10] << std::string
I have #include<string> in my header to make sure my strings are working as they should.
I tried std::string("direction") and still the issue was same.
Beginner in C++. Help would be appreciated.
operator<< isn't used for arbitrary string concatenation - it is called an "output stream operator", and it is only used in the context of std::ostream.
When you say...
std::cout << tag << " :" << s << std::endl;
...you're actually writing code roughly equivalent to:
std::cout.operator<<(tag).operator<<(" :").operator<<(s).operator<<(std::endl);
As you can see operator<< knows how to work with std::cout and std::string, but not between strings.
In order to concatenate std::string instances, you can simply use operator+:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
Please note that this concatenation technique is not the most efficient: you might want to look into std::stringstream or simply use std::string::reserve to avoid unnecessary memory allocations.
Substitute the << with the + operator as you are manipulating the string, not the stream:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
If you're determined to use the operator<< notation you need an object that understands it.
Here's such an object (I make no claims that this is a good idea):
#include <string>
#include <sstream>
#include <iostream>
void log(std::string s) {
std::string tag = "main";
std::cout << tag << " :" << s << std::endl;
}
struct string_accumulator
{
std::ostringstream ss;
template<class T>
friend string_accumulator& operator<<(string_accumulator& sa, T const& value)
{
sa.ss << value;
return sa;
}
template<class T>
friend string_accumulator& operator<<(string_accumulator&& sa, T const& value)
{
return operator<<(sa, value);
}
operator std::string () { return ss.str(); }
};
inline auto collect() -> string_accumulator
{
return string_accumulator();
}
int main()
{
int direction = 1;
int count = 1;
log(collect() << "direction" << std::to_string(direction) << ", count: " << std::to_string(count));
}
The prototype of your function is void log(std::string s);. It awaits for an std::string. So you need to pass a string to it, not a stream!
So, change this:
log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
to this:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
where I only changed the << operator to + operator. It will now concatenate everything inside the parentheses to a single std::string.
Your attempt implies that you wanted to pass std::ostream as the parameter. Maybe you want to read C++ Passing ostream as parameter. However, if I were you, I would just overload <<.
why don't you use:
// just include thisusing namespace std;
#include <conio.h> // include conio.h file
#include <iostream.h> // or #include<iostream>
int main()
{
int cout = 5;
cout << cout;
return 0;
}
Why does this happen ??
The code compiles correctly but it does not give expected output when it runs
This does not give the output 5 and all other stuff
It also does not give a warning.
The following line declares an int that happens to be called cout (it is not the std::cout stream)
int cout = 5;
The << operator peforms a bit shift.
So
cout << cout;
is only performing a bit shift and not storing the result.
To clarify, have a look at the following program:
#include<iostream>
int main()
{
int cout = 5;
auto shiftedval = cout << cout;
std::cout << "cout's value is " << cout << ", and the result of the bit shift is " << shiftedval << '\n';
return 0;
}
It will output:
cout's value is 5, and the result of the bit shift is 160
What is happening behind the scenes is that operator<< has been overloaded to take an ostream on the left hand side.
By including iostream you get this function and the compiler will know what you mean if you have an ostream to the left of the << operator.
Without a library the << would just simply have been a bitwise shift operator.
Also note that if you had ill-advisedly included using namespace std; or using std::cout then cout would then mean ostream and << would trigger a call to the library operator<< function. If after adding the using declaration above you include another declaration of cout the newly declared name will hide the previous declaration and cout will now be considered an int again and we're back to the bit shift operator functionality being used.
Example:
#include<iostream>
using namespace std; // using std:: at global scope
int main()
{
int cout = 5;
auto shiftedval = cout << cout;
//the following will not compile, cout is an int:
cout << "cout's value is " << cout << ", and the result of the bit shift is " << shiftedval << '\n';
//but we can get the cout from the global scope and the following will compile
::cout << "cout's value is " << cout << ", and the result of the bit shift is " << shiftedval << '\n';
return 0;
}
You are naming your variable cout, which you are confusing with std::cout. Your example preforms a bit shift operation. Try this instead :
int main()
{
int cout = 5;
std::cout << cout;
return 0;
}
Better yet, name your variable anything else to avoid the confusion :
int main()
{
int foo = 5;
std::cout << foo;
return 0;
}
If you don't explicitly declare the std namespace, either by including using namespace std; in your code or calling std::cout then cout resolves to the local variable cout in your main() function.
Even if you do declare using namespace std; cout will still resolve to the local variable instead - this is one reason why a lot of people, books, and tutorials will recommend that you explicitly write std::whatever instead of using the namespace.
So I've been set a task to create a temperature converter in C++ using this equation:
Celsius = (5/9)*(Fahrenheit – 32)
and so far I've come up with this (I've cut out the 10 lines worth of comments from the start so the code posted begins on line 11, if that makes any sense)
#include <iostream>
#include <string>
#include <iomanip>
#include <cmath>
using namespace std;
int main ()
{
float celsius;
float farenheit;
std::cout << "**************************" << endl;
std::cout << "*4001COMP-Lab5-Question 1*" << endl;
std::cout << "**************************" << endl << endl;
std::cout << "Please enter a temperature in farenheit: ";
std::cin >> farenheit >> endl;
std::cout << "Temperature (farenheit): " << endl;
std::cout << "Temperature (celsius): " << celsius << endl;
std::cin.get();
return 0;
}
Everytime I try to run this program I get a heap of errors with this one appearing every time:
1>m:\visual studio 2010\projects\week 5\week 5\main.cpp(26): error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::basic_istream<_Elem,_Traits>' (or there is no acceptable conversion)
I've tried everything I can think of to get rid of this error but it reappears every time, any idea on how to fix this?
std::cin >> farenheit >> endl;
This statement is invalid. remove >> endl from it.
std::cin >> farenheit ;
This statement is only valid when you cout something. Like here.
std::cout << farenheit << endl ;
The reason is that endl is the end-line character used to output a new line. So only the output stream accepts it. You can look up more about return values and prototypes of cin and cout here.
http://en.cppreference.com/w/cpp/io
std::endl is actually a function and the operator to stream into it is not defined. Yes it's a confusing error message as it is complaining about the LHS not the RHS.
Its implementation is something like:
namespace std {
std::ostream& endl( std::ostream& os )
{
os << '\n';
os.flush();
return os;
}
}
Streaming has then defined something like this:
namespace std {
std::ostream & operator<<( std::ostream & os, (std::ostream& *)(std::ostream&) func )
{
return func(os); // or is it (*func)(os)
}
}
It's actually quite a "powerful" feature of iostream, because you can then write a function with that signature and stream the function into your stream to do stuff with the iostream.
That is in fact a similar concept as to how the <iomanip> library also works (although that uses objects).
How would someone do that?
for example I do like:
std::cout << "something";
then it should print the time before "something"
Make your own stream for that :) This should work:
class TimedStream {
public:
template<typename T>
TimedStream& operator<<(const T& t) {
std::cout << getSomeFormattedTimeAsString() << t << std::endl;
return *this;
}
};
TimedStream timed_cout;
void func() {
timed_cout << "123";
}
You'd be able to use this class for every type for which std::cout << obj can be done, so no further work is needed.
But please note that the time will be written before every <<, so you cannot chain them easily. Another solution with explicit timestamp is:
class TimestampDummy {} timestamp;
ostream& operator<<(ostream& o, TimestampDummy& t) {
o << yourFancyFormattedTimestamp();
}
void func() {
cout << timestamp << "123 " << 456 << endl;
}
You could use a simple function that prints the timestamp and then returns the stream for further printing:
std::ostream& tcout() {
// Todo: get a timestamp in the desired format
return std::cout << timestamp << ": ";
}
You would then call this function instead of using std::cout directly, whenever you want a timestamp inserted:
tcout() << "Hello" << std::endl;
ostream& printTimeWithString(ostream& out, const string& value)
{
out << currentTime() << ' ' << value << std::endl;
return out;
}
Generate current time using your favourite Boost.DateTime output format.
This looks like homework. You want something in the line of:
std::cout << time << "something";
Find a way the retrieve the time on your system, using a system call.
Then you'll have to implement a << operator for your system-dependent time class/struct.