On Sep 5, 8:41 am, Rajib <raji...@verizon.netwrote:
edu...@gmail.com wrote:
I have some code that compiles with gcc but fails with MS VC 8. I
would like to know which one is following the C++ standard.
istream& istr = false ? cin : ( * new ifstream("test.txt")) ;
Using g++ it compiles. Using MS VC 8 it fails with a message
along the lines of:
"cannot access private member declared in class
'std::basic_ios<_Elem,_Traits>' "
The code below however,
istream& istr = * new ifstream("test.txt") ;
compiles fine with MS VC8.
It seems it has to do with the outcome of the ?: operator,
which is generating a call to the copy constructor in the MS
compiler but not in g++ ...?
FWIW, the draft C++ standard says:
For every pair of promoted arithmetic types L and R, there exist
candidate operator functions of the form
24
LR operator?(bool, L , R );
where LR is the result of the usual arithmetic conversions between
types L and R.
For every type T, where T is a pointer or pointer-to-member type,
there exist candidate operator functions of the form
25
T operator?(bool, T , T );
,
so you can't use the ? operator on class types such as
ifstream (or maybe I'm completely wrong on this).
That's an interesting quote. It comes from the section on
overload resolution, and describes how the built-in operators
interact with user defined operators during overload resolution.
Since you can't overload ?:, I'm not sure that it's relevant to
anything. Section 5.16 describes ?: in detail, including all
relevant conversions. You very definitely can use user defined
types for the second and third operands.
I think that the standard is abiguous here. The second and
third arguments have different types (std::istream and
std::ifstream, respectively), but both are lvalues, and the
expression in the third argument can be implicitly converted to
istream& (lvalue reference to the type of the second argument).
There is a statement "If the second and third operands are
lvalues and have the same type, the result is of that type and
is an lvalue[...]"; it is not clear to me whether the "have the
same type" here applies before or after the above conversion.
(Logically, I would expect that it happens after, which would
make the statement legal.)
Also, historically at least, cin wasn't always an istream, but
rather some class derived from istream. I don't think that the
actual wording in the current standard allows this (although I'm
not sure that it was forbidden intentionally), but it wouldn't
surprise me if some implementations still did have a cin which
was a derived class. If the type of cin is neither a base class
of nor derived from std::ifstream, then the statement definitely
shouldn't compile.
Both problems can be solved simply by casting the results of the
new to std::istream* before dereferencing it.
If you could, you'd probably need to be able to access the
copy constructor. In any case, you could just use ? operator
on the pointer:
istream& istr = *(false ? &cin : ( new ifstream("test.txt")) );
This would solve the lvalue problem, above, if that's the actual
problem, but it still wouldn't work if cin wasn't an
std::istream, but rather a class derived from std::istream.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34