This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Bug or feature? C++ code that no longer compiles under GCC 4.2
- From: Joe Buck <Joe dot Buck at synopsys dot COM>
- To: Magnus Fromreide <magfr at lysator dot liu dot se>
- Cc: Daniel Drake <ddrake at brontes3d dot com>, gcc at gcc dot gnu dot org
- Date: Thu, 30 Aug 2007 14:55:12 -0700
- Subject: Re: Bug or feature? C++ code that no longer compiles under GCC 4.2
- References: <1188420167.8141.3.camel@localhost> <1188507063.3840.4.camel@localhost>
On ons, 2007-08-29 at 16:42 -0400, Daniel Drake wrote:
> > #define BREAK_GCC4_2
> >
> > template<typename Op>
> > void foo(Op& op) { op(); }
> >
> > class My {
> > public:
> > static void myOp() { }
> >
> > void test() {
> > #ifdef BREAK_GCC4_2
> > foo(myOp);
> > #else
> > foo(My::myOp);
> > #endif
> > }
> > };
On Thu, Aug 30, 2007 at 10:51:03PM +0200, Magnus Fromreide wrote:
> I think this is a feature, and your old code were buggy.
>
> ISO 14882:1998 states (§5.3.1p3)
>
> > A pointer to member is only formed when an explicit & is used and its
> > operand is a qualified-id not enclosed in parentheses.
But taking the address of myOp does not produce a pointer-to-member,
as it is a static function; &My::myOp is a pointer to an ordinary
function.
Just the same, you need the & to make an ordinary pointer-to-function
as well. Then the other problem is the attempt to bind a non-lvalue
to a non-const reference. If I fix both of those problems, I get
template<typename Op>
void foo(const Op& op) { op();}
class My {
public:
static void myOp() {}
void test() {
foo(&myOp);
}
};
and 4.2.1 accepts it. However, if I omit the ampersand and write
template<typename Op>
void foo(const Op& op) { op();} // line 2
class My {
public:
static void myOp() {}
void test() {
foo(myOp); // line 8
}
};
I get
foop_noamp.cpp: In member function 'void My::test()':
foop_noamp.cpp:8: error: invalid initialization of non-const reference of type 'void (&)()' from a temporary of type 'void ()()'
foop_noamp.cpp:2: error: in passing argument 1 of 'void foo(const Op&) [with Op = void ()()]'
The error message here is bogus; there is no non-const reference.
So for users, the message is to use an ampersand to form the
pointer-to-function or pointer-to-member, and to use a const reference
if you aren't passing an lvalue.