Re: Use of operator T const& to get a reference to self
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),[..]"
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 ;-)
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).
Concluding, I would say that a bug report for gcc seems a
reasonable choice.
Greetings from Bremen,
Daniel
---
[ 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 ]