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.