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

2007-08-30 Thread Daniel Drake
On Thu, 2007-08-30 at 10:05 +1000, Jonathan Adamczewski wrote:
 I don't have gcc-4.2 handy - does changing this to a const reference 
 solve the problem? i.e
 
 templatetypename Op
 void foo(const Op op) { op(); }

Thanks for the suggestion, it doesn't help:

test.cpp: In member function 'void My::test()':
test.cpp:12: error: invalid initialization of non-const reference of
type 'void ()()' from a temporary of type 'void ()()'
test.cpp:4: error: in passing argument 1 of 'void foo(const Op) [with
Op = void ()()]'

-- 
Daniel Drake
Brontes Technologies, A 3M Company
http://www.brontes3d.com/opensource



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

2007-08-30 Thread Magnus Fromreide
On ons, 2007-08-29 at 16:42 -0400, Daniel Drake wrote:
 Hi,
 
 Take the following code sample:
 
 
 #define BREAK_GCC4_2
 
 templatetypename 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
   }
 };
 
 
 It compiled fine under GCC 4.1 but fails under 4.2.0:
 $ g++ -c test.cpp
 test.cpp: In member function 'void My::test()':
 test.cpp:12: error: invalid initialization of non-const reference of
 type 'void ()()' from a temporary of type 'void ()()'
 test.cpp:4: error: in passing argument 1 of 'void foo(Op) [with Op =
 void ()()]'
 
 We found an alternative way to make the code compile (comment out the
 first line) which works with both versions, but I'm wondering whether
 this should be reported as a bug or if it was intentional.

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.

and then goes on to say (in a note, so this isn't normative)

 Nor is unqualified-id a pointer to member, even within the scope of 
 the unqualified-id's class.

/MF




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

2007-08-30 Thread Joe Buck

On ons, 2007-08-29 at 16:42 -0400, Daniel Drake wrote:
  #define BREAK_GCC4_2
  
  templatetypename 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

templatetypename 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

templatetypename 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.





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

2007-08-29 Thread Daniel Drake
Hi,

Take the following code sample:


#define BREAK_GCC4_2

templatetypename 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
  }
};


It compiled fine under GCC 4.1 but fails under 4.2.0:
$ g++ -c test.cpp
test.cpp: In member function 'void My::test()':
test.cpp:12: error: invalid initialization of non-const reference of
type 'void ()()' from a temporary of type 'void ()()'
test.cpp:4: error: in passing argument 1 of 'void foo(Op) [with Op =
void ()()]'

We found an alternative way to make the code compile (comment out the
first line) which works with both versions, but I'm wondering whether
this should be reported as a bug or if it was intentional.

Thanks!
-- 
Daniel Drake
Brontes Technologies, A 3M Company
http://www.brontes3d.com/opensource