Here I define a Date
, and specify a user-defined conversion.
class Date {
private:
int day;
int month;
string dateStr;
public:
Date(int _day, int _month) : day(_day), month(_month) {}
operator const string() {
ostringstream formattedDate;
formattedDate << month << "/" << day;
dateStr = formattedDate.str();
return dateStr;
}
};
It works well when converting to string
.
Date d(1, 1);
string s = d;
But why cannot use it with cout
directly?
cout << d << endl; // The compiler complains that there is no suitable type marching << operator
However, if I use char*
instead of string
for user-defined conversion, I can use it with cout
directly. Why?
operator const char*() {
ostringstream formattedDate;
formattedDate << month << " / " << day;
dateStr = formattedDate.str();
return dateStr.c_str();
}
ps. I know that overloading <<
directly will work well for output. But my question is: why cannot use <<
with user-defined conversion to std::string
?
This may happen because std::cout is writing to output buffer which is waiting to be flushed. If no flushing occurs nothing will print. So you may have to flush the buffer manually by doing the following: std::cout.
The std::cout ObjectStd::cout is the preferred way to print a string in C++.
You need to put it in a function. You need to #include <string> before you can use the string class and iostream before you use cout or endl . string , cout and endl live in the std namespace, so you can not access them without prefixing them with std:: unless you use the using directive to bring them into scope first.
As for why it is so "time consuming", (in other words, slow,) that's because the primary purpose of std::cout (and ultimately the operating system's standard output stream) is versatility, not performance.
Note that std::string
is an instantiation from template std::basic_string
, the signature of operator<<
for std::string
is indeed:
template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const std::basic_string<CharT, Traits, Allocator>& str);
then for cout << d;
, the template parameter of std::basic_string
has to be deduced; but type deduction does not consider implicit conversions;
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
That means the deduction would fail; then no candidate function is viable.
But operator<<
for const char*
hasn't such kind of problem; implicit conversion takes effect and then works fine.
To solve the issue, you can use explicit conversion to avoid template argument deduction; or overload operator<<
on the type Date
directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With