Re: Use of operator T const& to get a reference to self
On Mar 29, 9:52 pm, "Daniel Kr?gler" <daniel.krueg...@googlemail.com>
wrote:
James Kanze schrieb:
Given the following program:
#include <locale>
class FG
{
public:
explicit FG( std::locale const& l )
: myLoc( &l ) {}
template< typename F >
operator F const&() const
{
return get< F >( *myLoc, &std::use_facet ) ;
}
private:
std::locale const* myLoc ;
template< typename F >
F const& get( std::locale const& l,
F const& (*f)( std::locale const& ) ) const
{
return (*f)( l ) ;
}
} ;
FG
getF( std::locale const& l )
{
return FG( l ) ;
}
void
f()
{
std::ctype< char > const& ct = getF( std::locale() ) ;
}
G++ (4.1.0) instantates the template operator F const& to get
the const reference needed to call the copy constructor (which
of course fails to compile, since use_facet<FG> is not legal).
Providing a non-template:
operator FG const&() const { return *this ; }
solves the problem, but is g++ correct here? I would have
expected the temporary "FG( l )" to bind directly to the const
reference of the (compiler generated) copy constructor.
Or maybe my question is: is this intentional? Given ?8.5.3/5,
"[...]If the initializer expression [...]-- has a class type [it
does] and can be implicitly converted to an lvalue of type "cv3
T3", where "cv1 T1" is reference-compatible with "cv3 T3" [...]
then [...] the reference is bound to the lvalue result of the
conversion [...]" But it doesn't seem at all natural to have a
user defined conversion called for a copy.
An interesting question, but IMO the standard is quite clear
here, because 12.3.2/1 says unambigiously:
"[..] A conversion function is never used to convert a (possibly
cv-qualified) object to the (possibly cv-qualified) same object
type (or a reference to it),[..]"
OK. That's the sentence I was looking for. Unless there's
something I've misunderstood, I'm copying FG, and the conversion
operator was being used to initialize the FG const& parameter of
the (implicitly declared and defined) copy constructor.
This sentence exists since the 1998 standard and has also
not changed in the current draft. I considered for a while that
gcc might not view a temporary as an object, but this seems
also rather clearly expressed in both 1.8 and 12.2.
I observed that even my quite old mingw gcc 3.4, a rather old
Borland Compiler (I just can't find its version number) and
MS-VS2003 show the unexpected behaviour you mention.
But no newer compiler I tested (including all public available
Comeau online versions and MS-VS2005-SP1) did. Of course
we have no majoritarian decision here, but I tend to say that
the standard is unusually unmistakable here ;-)
The sentence you quoted is exceptionally clear. To discharge
the compiler vendors some, however: this could have been
mentionned in the the section on binding to a reference. If I
were writing a compiler, that's the section I'd be following in
detail when writing the relevant code, and I'd probably have
missed this one particular case as well.
All newer compilers follow rather strict the mentioned rule:
To enforce this, I simply added the operator FG(FG&) to your
class and none (except the older ones) tried the conversion
operator but gave up with something like "class "FG" has no
suitable copy constructor".
As a not very relevant sidenode: Even by using the language
extension mode of MS-VS2005 the compiler did not do that
but selected instead the actually forbidden FG(FG&) c'tor with
a corresponding warning
"nonstandard extension used : 'argument' : conversion from 'FG'
to 'FG &' A non-const reference may only be bound to an lvalue;
copy constructor takes a reference to non-const") warning).
A reasonable choice, given that earlier versions didn't even
warn when binding a temporary to a non-const reference. (Sun CC
uses the word "anachronism" for this sort of thing.)
Concluding, I would say that a bug report for gcc seems a
reasonable choice.
Sounds right to me. (To be fair, I should probably install the
latest version, and try it first. But unless there's already a
bug report on it, I'd be surprised if the behavior changed.)
--
James Kanze (GABI Software) email:james.kanze@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
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]