I have simple lines of code, where I am using insertion operator << to show hello world string. If I use a operator b then it should result to a.operator(b); I try to do same thing with insertion operator and in output I got address of string, rather than actual string.
std::cout<<"Hello world"<<std::endl;
std::cout.operator<<("Hello world").operator<<(std::endl);
Output:
Hello world
0120CC74
I am using Visual Studio.
Does my operator conversion has any problem?
std::cout<<"Hello world"<<std::endl;
use overloaded output operator for const char*, that is free function, not member function.
std::cout.operator<<("Hello world").operator<<(std::endl);
use overloaded output operator for const void*, since const char* is implicitly convertible to const void*.
You can look at member overloads here and free overloads here
My bet is that member function operator for std::ostream(char*) is not overloaded.
If you look at ostream::operator<<, void* is best match and char* naturally gets converted to it, while global operator<<(std::basic_ostream), has exact overloads for char* types, which gets picked up.
Of course, they behave differently.
As the other answers say, the problem is that you are explicitly calling the member function operator <<, which is not overloaded for const char*.
To get the const char* overload, you need to call the free operator << function, which is appropriately overloaded:
operator<<(std::cout, "Hello World").operator<<(std::endl);
Similarly, there is no free function overload of operator << for writing an std::ostream& (*)(std::ostream&), so for std::endl you have to use the member function.
From this, we can see that you can not rewrite from the infix operator syntax (std::cout << ...) to function calling syntax (operator << (...)) without losing generality.
Related
Everybody knows that you can't concatenate 2 string literals using the + operator.
#include <iostream>
int main() {
std::cout << "hello " + "world";
}
// Error
What's happening here is that you are trying to add 2 char* which is an error. You can however add a string literal to a std::string.
#include <iostream>
int main() {
std::string s = "hello ";
std::cout << s + "world";
}
// Fine, prints hello world
But what I found is that the below code is also valid.
#include <iostream>
int main() {
std::string s = "world";
std::cout << "hello " + s;
}
// Fine, prints hello world
I would imagine in the above example that you are trying to add a std::string to a char* but it works fine. I think it may just be using the std::string overload of the + operator. My question is what exactly is happening here and how does the operator decide which overload to use in a situation such as with 2 different classes with perfectly valid overloads being added together.
What's happening here is that you are trying to add 2 char* which is an error.
To be a bit more correct, you're trying to add two arrays, each of which decay to const char*.
My question is what exactly is happening here
You're using these overloads:
std::string
operator+(const std::string& lhs, const char* rhs);
std::string
operator+(const char* lhs, const std::string& rhs);
how does the operator decide which overload to use
It uses the same overload resolution as normal functions do. The complete and precise description won't fit within this answer since overload resolution is quite complex.
In short: There is a list of all functions by the same name. This is the overload set. If all arguments (operands in case of operator overload) can be converted to the formal parameters of the function, then that function is a viable candidate for the overload resolution. The candidates are ranked by a set of rules. Candidate requiring "less" conversion is ranked higher. If one candidate is unambiguously the most highly ranked candidate, then that overload will be called; otherwise there is an error.
Operator precedence : + has higher rank than <<, hence the line is parsed as:
(std::cout << ("hello " + s) );
And operator+(const char*,const std::string&) is the one on place 4 here: https://en.cppreference.com/w/cpp/string/basic_string/operator%2B.
Maybe you are a little surprised, because often operators are member functions and that implies that the left operand would need to be the std::string. However, thats not always the case. Operators can be free functions.
How does stringstream work when you do this:
stringstream ss;
ss << "123" << "abc";
Does it create a throwaway "123abc" string or does it do both operations consecutively to the stringstream?
I would like to replicate that functionality but no overload I do seems to work with two parameters like the above code...
It's the equivalent of doing two seperate function calls of the << operator:
(ss.operator<<("123")).operator<<("abc")
so yes, it does both operations "consecutively".
Actually it is equivalent to this:
std::operator<<(std::operator<<(ss, "123"), "abc");
Note that there is no member function which takes const char* as argument. It is a non-member function, and ss is passed to it as first argument and const char* is passed as second argument. The function returns std::ostream& which then passed to it again. It is more like this:
print( print (ss, "123"), "abc"); //just for clarity
which means there are two function calls. Replace print with std::operator<<. Everything will be clear now.
Hope that helps.
The other answer which says this:
(ss.operator<<("123")).operator<<("abc") //copied from other answer (wrong)
is wrong! It is wrong because it assumes that operator<< which takes const char* as argument is a member function which is not true!
std::stringstream::operator<<(const char*) returns a std::stringstream&.
This technique lets you "chain" it.
This is not quite true -- but it is pretty much equivalent to the truth for your purposes.
A slightly more accurate statement is that std::stringstream& operator<<(std::stringstream&, const char*) can be chained.
An even more accurate statement is that ostream& operator<<(ostream&, const char*) exists, and std::stringstream is an ostream, then overload resolution on << calls it.
I am curious if std::cout has a return value, because when I do this:
cout << cout << "";
some hexa code is printed. What's the meaning of this printed value?
Because the operands of cout << cout are user-defined types, the expression is effectively a function call. The compiler must find the best operator<< that matches the operands, which in this case are both of type std::ostream.
There are many candidate operator overloads from which to choose, but I'll just describe the one that ends up getting selected, following the usual overload resolution process.
std::ostream has a conversion operator that allows conversion to void*. This is used to enable testing the state of the stream as a boolean condition (i.e., it allows if (cout) to work).
The right-hand operand expression cout is implicitly converted to void const* using this conversion operator, then the operator<< overload that takes an ostream& and a void const* is called to write this pointer value.
Note that the actual value resulting from the ostream to void* conversion is unspecified. The specification only mandates that if the stream is in a bad state, a null pointer is returned, otherwise a non-null pointer is returned.
The operator<< overloads for stream insertion do have a return value: they return the stream that was provided as an operand. This is what allows chaining of insertion operations (and for input streams, extraction operations using >>).
cout does not have a return value. cout is an object of type ostream. operator << has a return value, it returns a reference to cout.
See http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/ for reference.
The only signature that matches is:
ostream& operator<< (ostream& ( *pf )(ostream&));
so it returns the pointer to the operator<< member.
the one in James' answer. :)
I believe that would be the address of the ostream object that "" got printed to
I'm trying to make a class, let's say MyClass, work under the following condition:
MyClass name = "everyone"; // Assigns "everyone" into a local string variable.
printf_s("Hello %s!", name); // Should output "Hello everyone!" without the quotes.
I've tried overloading operator const char*() as well as operator char*() but neither seem to do the trick.
If you overload it with operator const char*, you can explicitly cast it:
MyClass name = "everyone";
printf_s("Hello %s!", (const char*)name);
// prints "Hello everyone!"
And then it will behave properly. It doesn't work implicitly becase printf can take any type of parameter after the first one, so the compiler has no idea what to try to cast it to.
This assumes, of course, that operator const char* of your class returns the C-style string everyone.
As Tomalak Geret'kal noted in the comments, making your class implicitly castable to const char* could cause a lot of problems because it can cast itself without you knowing/wanting it to.
As Kerrek SB also pointed out, it's probably not worth making your class compatible with printf, since this is C++ after all. It would be better style to write an operator<< overload for ostream&s:
ostream& operator<<(ostream& rhs, const MyClass& c) {
rhs << c.name; // assuming the argument to the constructor
// is stored in the member variable name
return rhs;
}
MyClass name = "everyone";
cout << "Hello " << name << '!';
// prints "Hello everyone!"
You cannot "detect" the intention of being converted to a char const* when being passed into an ellipsis (...). Your object will just be put on the stack and you'll probably crash. This is different than if your object is passed in to a function that explicitly takes a char const*, in which case an implicit conversion operator can be triggered.
I would recommend going the same route as the standard library and rely as little as possible on implicit conversions. Instead, use a c_str() member or something.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Overloading operator ->
Hi,
I've seen that operator->() is chained (re-applied) after it is evaluated, for example:
struct Bar
{
Bar() : m_str("Hello world!") {}
const string* operator->() const { return &m_str; }
string m_str;
};
struct Foo
{
const Bar& operator->() const { return m_bar; }
Bar m_bar;
};
int main()
{
Foo f;
cout << f->c_str() << endl;
return 0;
}
works pretty fine, which requires three operator->() to be evaluated - Foo::operator->(), Bar::operator->() and regular pointer resolution.
But it wont work with pointers in the middle - if Foo::operator->() returns pointer to Bar instead of reference, it wont compile. Same happens with auto_ptr<auto_ptr<string>> for example.
Is it specific to non-overloaded operator->() so it is only applied once and does not cause chaining?
Is it possible to make code below works without using (*ptr2)-> ...?
int main()
{
string s = "Hello world";
auto_ptr<string> ptr1(&s);
auto_ptr<auto_ptr<string> > ptr2(&ptr1);
cout << ptr1->c_str() << endl; // fine
cout << ptr2->c_str() << endl; // breaks compilation
}
Thanks!
C++98 standard §13.5.6/1 "Class member access":
An expression x->m is interpreted as (x.operator->())->m for a class object x of type T if T::operator-> exists and if the operator is selected at the best match function by the overload resolution mechanism (13.3).
What this means in practice is that when x is a pointer, you don’t get chaining; you then just get the built-in operator-> (i.e. x->m with x a pointer translates to (*x).m).
But when x is an object of class type T, then you can get the chaining effect. Because then the interpretation as (x.operator->())->m can be that (x.operator->()) itself is an object of some class, say class U. Whence the second -> can be resolved as U::operator->, and so on, if the result of that again is a class type object…
Like, in your case, Foo::operator-> produces (a reference to) an object of class Bar, which does define an operator->.
But when operator-> returns a pointer, as e.g. std::auto_ptr<T>::operator-> does, then it's just the built-in operator-> that's used.
In passing, the chaining can be used to practically prevent someone from using delete inappropriately. std::auto_ptr does not do that. And I’ve never seen it done.
But there was once a long discussion thread over in [comp.lang.c++.moderated] about how to prevent inadvertent delete of the raw pointer managed by a smart pointer, and this was one possibility that was discussed.
Cheers & hth.
The reason your first example works is because you returned a reference instead of a pointer. That operator would normally be invalid except in the case that it is overloaded. Therefore, the compiler must execute the overloaded functions down the chain. However, in the case of auto_ptr you actually are returned a real pointer and the default operator -> is invoked for regular pointers.
Please see the Overloading operator -> question for more details.
No, it is not possible for it to work. If you could overload operator -> for string * you could make it work. But operator -> already has a definition for all pointer types. So, just like you can't overload + for primitive numeric types, you can't overload operator -> for any pointer type.
And even if you could, how could the compiler know when the recursion should end?