This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bug or feature? C++ code that no longer compiles under GCC 4.2


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.




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]