RE: Automatic invocation of conversion function: operator std::ostream
Hi,
2) the compiler discovers that the object finds itself to the
left of '<<'operator that is not defined in this class;
3) the compiler finds a conversion function and tries that:
it returns std::ostream& for which the operator is defined;
I don't think the above assumptions would be true.
There is no builtin relationship between your N::Log object and std::cout
object, so the compiler cannot convert your N::Log object to the
std::basic_ostream(std::cout) automatically. You need to provide that
class' own '<<' operators respectively.
the introduction of a '<<' operator into that namespace's
scope made it available to the compiler. What needs to
be done to make '<<' defined in 'std' namespace available
to the compiler in this instance in the same way?
your sample code is a chain expression, the truth is the first successfully
'<<' operation function call just returns a std::ostream object reference
for its following '<<' operator calls, in this case, the following '<<'
operator calls will use the std::cout& as its first operand. For example:
//only defined std::ostream& operator <<(std::ostream& os, bool i) in N::Log
N::Log(N::Log::INF) << 2.5 << " " << 2.5 << " A string" << std::endl;
Output:
1 2.5 A string
The code could be parsed into the following 2 sub pieces:
1. N::Log(N::Log::INF) << 2.5 --> Output: 1
convertion 2.5L to bool value true(1), returns std::cout&
(std::ostream&)
2. std::cout << " " << 2.5 << " A string" << std::endl;
Output: 2.5 A string
Thanks!
Best regards,
Gary Chang
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
Thread-Topic: Automatic invocation of conversion function: operator
std::ostream
thread-index: Aca+9Hqt7ogbVKFxSj2QK6je/+gErA==
X-WBNR-Posting-Host: 80.177.9.143
From: =?Utf-8?B?UGF1bA==?= <vhr@newsgroups.nospam>
Subject: Automatic invocation of conversion function: operator std::ostream
Date: Sun, 13 Aug 2006 09:21:06 -0700
Lines: 103
Message-ID: <FCC8CD33-B6E0-43C4-8F64-2DC05F69EDDC@microsoft.com>
MIME-Version: 1.0
Content-Type: text/plain;
charset="Utf-8"
Content-Transfer-Encoding: 8bit
X-Newsreader: Microsoft CDO for Windows 2000
Content-Class: urn:content-classes:message
Importance: normal
Priority: normal
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.1830
Newsgroups: microsoft.public.vc.language
Path: TK2MSFTNGXA01.phx.gbl
Xref: TK2MSFTNGXA01.phx.gbl microsoft.public.vc.language:249644
NNTP-Posting-Host: TK2MSFTNGXA01.phx.gbl 10.40.2.250
X-Tomcat-NG: microsoft.public.vc.language
Hello,
I am working on a class for logging messages into a log file allowing for
the following syntax:
N::Log(N::ERR) << "Here goes the error message: integer = " << i << ",
long
= " << l << std::endl;
(where ???N???is a namespace, N::ERR, severity, and ???i???and ???l???
variables)
I reasoned that the ???Log??? being a temporary object, would be ideal for
locking the file (std::ofstream) till the end of output (its destructor
will
only be invoked at the end of the full expression; obviously the
multi-threaded library protects the stream but output can still be
pre-empted
after each ???<???. ???Log???was not meant to do anything but the handling
of
locking, so to invoke real output I added ???operator std::ostream&()???to
it
that would return a file stream (std::ofstream) declared at the namespace
level, and this was where I encountered a problem.
As far as I know, a compiler will try various conversion functions in the
hope of finding a meaningful interpretation of ???<??? This works without
problems for built-in types (???operator int()???does get invoked if an
object
that defines it finds itself to the left of ???<???in an expression) but
so far
I cannot say I have complete understanding of the behaviour of
user-defined
types in this scenario, nor could I find anything that would say the
behaviour sought in this case is only limited to built-in types.
So, again, the behaviour I expected was:
1) N::Log(N::ERR): a temporary Log object is created; its constructor
accepts, say, a single parameter indicating severity and locks the log
file;
2) the compiler discovers that the object finds itself to the left of
???<???
operator that is not defined in this class;
3) the compiler finds a conversion function and tries that: it returns
std::ostream& for which the operator is defined;
4) with output complete, the temporary object is destroyed and its
destructor unlocks the lock and releases the log file.
Here is the complete code save for the lock which is uniquely
uninteresting:
#include <iostream>
#include <string>
namespace N {
std::ostream& log_file(std::cout);
class Log {
public:
enum Severity {ERR, INF, TRC};
Log(Severity s) {}
operator std::ostream &() { return log_file; }
};
}
int main()
{
std::cout << "Started.\n";
N::Log(N::Log::INF) << std::string("string: ") << std::string("Hello!\n");
N::Log(N::Log::INF) << std::string("int: ") << 1 << ", long: " << 1L <<
",
double: " << 1.5 << ", bool: " << true << std::endl;
std::cout << "Press any key to exit...\n";
char c;
std::cin.get(c);
}
(Tried with both Visual Studio 2003 and 2005 with the same results.)
This code will not compile as written but the addition of these two
operators at the end of the N namespace:
namespace N {
// ...
std::ostream& operator <<(std::ostream& os, bool i)
{
return os.operator <<(i);
}
std::ostream& operator <<(std::ostream& os, const std::string& s)
{
return std::operator <<(os, s);
}
}
will actually make things work which gives me a glimmer of hope. For one
thing, having only added ...operator(..., bool) brings all others (int,
double) into the scope (see main()) (the std::string???s operator << is
defined
separately, so has to be included also separately). (One other strange
thing
that I noticed is the need to convert the first quoted output explicitly
to
string (std::string(???Hello!???), not required for subsequent <<'s within
the
expression.)
I tried ???using std::operator <<;???and even ???using namespace std;???
all to no
avail. Defining the Log class within the std namespace (namespace std {
class
Log {...}; //... } did not help, either, although in that case there was a
warning that, say, ???int???will be truncated (only the ...operator
<<(...,
bool) being defined).
Is there something with the syntax that I missed?
Thank you.