Re: stream operator << overload resolution: temporaries vs non-tem
"Igor Tandetnik" wrote:
As an extension, MSVC allows binding temporaries to non-const
references. This conversion is the lowest ranking one, only used when no
other alternative is available. Try building with /Za (strict ANSI
conformance), you should get an error.
std::ostream& operator <<(std::ostream&, const std::string&);
std::ofstream("test.txt") << std::string("Hello!") << std::endl;
(I debugged and checked: it does call the above operator << for
strings.)
Don't you get a warning about a non-standard feature being used?
I did when I changed the level from /W3 to /W4.
2) Why would it work on subsequent insertions:
std::ofstream("test.txt") << "Hello!" /*returns address*/ << ' ' <<
"Hello!" << std::endl;
The subsequent insertion is called on a reference returned by the
previous insertion. The compiler has no way to know this reference
refers to a temporary. Consider:
struct C {
C& detemporize() {return *this;}
};
void f(C&);
// does not compile: can't bind temporary to non-const reference
f(C());
f(C().detemporize()); // works
This was the effect I was trying to achieve - that would work automatically,
though - through the use of the operator std::ostream&() (mentioned in the
original posting). Casting is certainly available to adjust the compiler's
perceptions, and when I applied static_cast to the temporary - to make it
static_cast<std::ostream&>(std::ofstream("test.txt")) - everything worked, as
though std::ofstream() were not a temporary. Judging from the compiler
errors, with the conversion "operator std::ostream&()" defined, the compiler
did take it into account but only added the new overload possibilities to
those available for a temporary producing a list of some 5 possibilities
(overloaded <<) it thought were of equal validity.
As an aside, obviously I am not trying to use a temporary file stream object
to write to a file in this way - was only trying to find a good way of
locking it until output is complete (lock, "write message" << var1 << ...,
unlock), for which a temporary seems to be uniquely suited - and works as
expected. To bring all << into scope required some work, though, since they
are all templates: if they were not templates, introducing the simple
operator std::ostream&() as above into any class would do the work, but since
they are, the only possible way seemed to me to derive the class for the
temporary from std::ostream. This has resolved the template argument lookup
but did not achieve the desired effect totally.
If the stream is treated as a constant object:
const std::ofstream& tmp = std::ofstream("test.txt");
tmp << "Hello!";
then the reference to the stream returned from this operation will
also be a constant?
This should not compile - you can't call non-const function through a
const reference.
It does not - only mentioned it as an illustration of how, I thought,
binding of a temporary to a constant reference works but got it slightly
wrong, though:
double temp = double(1);
const double& cr = temp;
(Stroustrup, p. 98)
And then, I reckoned, 'const double&' may only pass through functions that
do not alter it and if they do return it, then the return type would also be
'const double&'. But I obviously took the point of its being a Microsoft
extension anyway, so will avoid it.
Paul