rfg@riunite.ACA.MCC.COM (Ron Guilmette) (04/12/89)
Sorry to trouble you all, but I am still trying to absorb the fine points of this language. Can one of the language lawers who frequent this group please take a minute or two to answer a few simple legality questions for me. I would appreciate it a lot. I would like answers based either on cfront 2.0 or on the more abstract notion of the "formal language" rules" as they are now. ------------------------------------------------------------------------ What should (or does) happen if a given class inherits multiple new operators or multiple delete operators from multiple base classes? (This question assumes that MI has been implemented). Is it legal for an "operator new" to return anything other than a type "void*" result? Is it legal for an "operator new" to accept anything other than a single argument of type "long"? (By the way... why is the argument type "long" rather than type "unsigned long"?) Is it legal for an "operator delete" to return anything other than type "void"? Is it legal for a "global" operator delete to have a formal argument list which consists of anything other than a single formal parameter of type "void*"? Is it legal for a "class-specific" operator delete method to have a formal argument list which consists of anything other than a single formal argument of type "pointer to C" where type "C" is the containing class type? (I also have to wonder why class-specific delete operators need to have any "explicit" formal arguments. Don't these operators get a "this" pointer?) Can a union have public, private and protected parts? Can a union contain member functions? Can a data member and a method member declared within the same class have the same name? If so, what does &class_name::member_name yield in such cases. If a data member is declared in a base class, can it be redeclared as either data member or as a method member in a class derived from the given base class? If it can be redeclared as a data member in the derived class, must it be redeclared with the same data type? (Do the same rules apply as for method members which are redeclared in a derived class, i.e. can this mechanism be used to change the visibility of of an inherited data member in the same way that the visibility of method members may be modified, i.e. the way it is described on page 4 of the 1987 workshop proceedings?) If this kind of redeclaration is allowed, what would the expression &class_name::member_name yield in such cases? If a method member is declared in a derived class, can it be redeclared in a derived class as a data member? If this kind of redeclaration is allowed, what would the expression &class_name::member_name yield in such cases? Is it legal or illegal to try to take the address of an overloaded method or function using the '&' operator? Given a particular overloaded function or method that you absolutely *must* get the address of, is there any way of uniquely specifying a particular one of the overloadings? Specifically, is the following allowed (or will it ever be)? &class_name::overloaded_method_name(int,int) Is it legal to try to take the address of an overloaded operator for a given class (e.g. &my_class::operator+) even if that operator may have both unary and binary forms, so long as only one of these two forms is actually defined for the given class? Is it legal to declare a virtual method in a base class with a given parameter profile and then to declare a (virtual or plain) method with the same name but with a different parameter profile in a class which is derived from the given class? (GNU G++ thinks this is illegal). An example: class base { public: int method (int, int); }; class derived : public base { public: int method (float, float); // is this an error? }; Is there any acceptable way of getting at the address of a vtable for a given class. -- // Ron Guilmette - MCC - Experimental Systems Kit Project // 3500 West Balcones Center Drive, Austin, TX 78759 - (512)338-3740 // ARPA: rfg@mcc.com // UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg
bs@alice.UUCP (Bjarne Stroustrup) (04/12/89)
***> Ron Guilmette writes: Sorry to trouble you all, but I am still trying to absorb the fine points of this language. Can one of the language lawers who frequent this group please take a minute or two to answer a few simple legality questions for me. I would appreciate it a lot. ***> Simple? :-) I would like answers based either on cfront 2.0 or on the more abstract notion of the "formal language" rules" as they are now. ------------------------------------------------------------------------ What should (or does) happen if a given class inherits multiple new operators or multiple delete operators from multiple base classes? (This question assumes that MI has been implemented). ***> The usual algorithm for detecting ambiguities in a class lattice (see the evolution paper) is applied and if there is exactly one delete operator you use it; otherwise you have a compile time error. Is it legal for an "operator new" to return anything other than a type "void*" result? ***> No. Is it legal for an "operator new" to accept anything other than a single argument of type "long"? (By the way... why is the argument type "long" rather than type "unsigned long"?) ***> Yes. operator new can be overloaded (details ``real soon now'') Is it legal for an "operator delete" to return anything other than type "void"? ***> Yes. It can take an additional argument of type long (a size) Is it legal for a "global" operator delete to have a formal argument list which consists of anything other than a single formal parameter of type "void*"? ***> Yes (as above) Is it legal for a "class-specific" operator delete method to have a formal argument list which consists of anything other than a single formal argument of type "pointer to C" where type "C" is the containing class type? ***> Yes (as above) (I also have to wonder why class-specific delete operators need to have any "explicit" formal arguments. Don't these operators get a "this" pointer?) ***> No. They are applied after destruction. Can a union have public, private and protected parts? ***> No (though, this is being debated) Can a union contain member functions? ***> Yes. Can a data member and a method member declared within the same class have the same name? If so, what does &class_name::member_name yield in such cases. ***> No. If a data member is declared in a base class, can it be redeclared as either data member or as a method member in a class derived from the given base class? ***> Yes. If it can be redeclared as a data member in the derived class, must it be redeclared with the same data type? ***> No. (Do the same rules apply as for method members which are redeclared in a derived class, i.e. can this mechanism be used to change the visibility of of an inherited data member in the same way that the visibility of method members may be modified, i.e. the way it is described on page 4 of the 1987 workshop proceedings?) ***> Yes (but what is a ``method member'' I don't remember putting such a beast into C++ :-) If this kind of redeclaration is allowed, what would the expression &class_name::member_name yield in such cases? ***> A pointer to the member found in class_name or its bases using the usual ambiguity resolution mechanism. Essentially the one from the most derived class. If a method member is declared in a derived class, can it be redeclared in a derived class as a data member? ***> No (assuming you mean in the same derived class). You can only overload functions. If this kind of redeclaration is allowed, what would the expression &class_name::member_name yield in such cases? ***> It isn't. Is it legal or illegal to try to take the address of an overloaded method or function using the '&' operator? Given a particular overloaded function or method that you absolutely *must* get the address of, is there any way of uniquely specifying a particular one of the overloadings? ***> Yes. See the reference manual section 8.9. Essentailly, you can only take the address of an overloaded function if the context uniquely identifies which version. Specifically, is the following allowed (or will it ever be)? &class_name::overloaded_method_name(int,int) ***> no and no (that would be ambiguous with a call) Is it legal to try to take the address of an overloaded operator for a given class (e.g. &my_class::operator+) even if that operator may have both unary and binary forms, so long as only one of these two forms is actually defined for the given class? ***> Yes - even if they have both been declared. Is it legal to declare a virtual method in a base class with a given parameter profile and then to declare a (virtual or plain) method with the same name but with a different parameter profile in a class which is derived from the given class? (GNU G++ thinks this is illegal). An example: class base { public: virtual int method (int, int); }; class derived : public base { public: int method (float, float); // is this an error? }; ***> It is legal, but probably not what you want. The second method() hides the first one and do not redefine it (in the vtbl). Cfront thinks you made a mistake: "", line 9: warning: derived::method() hides virtual base::method() Is there any acceptable way of getting at the address of a vtable for a given class. ***> No. -- // Ron Guilmette - MCC - Experimental Systems Kit Project // 3500 West Balcones Center Drive, Austin, TX 78759 - (512)338-3740 // ARPA: rfg@mcc.com // UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg
ark@alice.UUCP (Andrew Koenig) (04/12/89)
In article <161@riunite.ACA.MCC.COM>, rfg@riunite.ACA.MCC.COM (Ron Guilmette) writes: > > Sorry to trouble you all, but I am still trying to absorb the fine > points of this language. > Can one of the language lawers who frequent this group please take a > minute or two to answer a few simple legality questions for me. > I would appreciate it a lot. I'll do my best. > What should (or does) happen if a given class inherits multiple > new operators or multiple delete operators from multiple base > classes? (This question assumes that MI has been implemented). You had better define a third operator new in the derived class if you intend to use `new' to allocate any objects of that class. Otherwise it's ambiguous and you'll get an error message. > Is it legal for an "operator new" to return anything other than > a type "void*" result? No. > Is it legal for an "operator new" to accept anything other than a > single argument of type "long"? (By the way... why is the argument > type "long" rather than type "unsigned long"?) Actually, the argument should be of type size_t. It's long in some present implementations but that'll change. > Is it legal for an "operator delete" to return anything other than > type "void"? No. > Is it legal for a "global" operator delete to have a formal argument > list which consists of anything other than a single formal parameter > of type "void*"? No. > Is it legal for a "class-specific" operator delete method to have a formal > argument list which consists of anything other than a single formal > argument of type "pointer to C" where type "C" is the containing class > type? (I also have to wonder why class-specific delete operators need > to have any "explicit" formal arguments. Don't these operators get a > "this" pointer?) Member operator delete has only a single argument, of type void*. It isn't C* because by the time operator delete is called, the memory in question no longer contains a C -- it has been destroyed. Member operator new and delete functions are static, so they don't have `this' available. > Can a union have public, private and protected parts? No. > Can a union contain member functions? No. > Can a data member and a method member declared within the same > class have the same name? If so, what does &class_name::member_name > yield in such cases. You can't overload data members. If you have a data member with a given name, you can't have a function member with the same name. > If a data member is declared in a base class, can it be redeclared > as either data member or as a method member in a class derived from > the given base class? If it can be redeclared as a data member > in the derived class, must it be redeclared with the same data type? Yes. It need not be redeclared with the same type. > (Do the same rules apply as for method members which are redeclared > in a derived class, i.e. can this mechanism be used to change the > visibility of of an inherited data member in the same way that > the visibility of method members may be modified, i.e. the way it > is described on page 4 of the 1987 workshop proceedings?) > If this kind of redeclaration is allowed, what would the expression > &class_name::member_name yield in such cases? I don't have my workshop proceedings handy -- how about an example of what you mean? > If a method member is declared in a derived class, can it be > redeclared in a derived class as a data member? Yes. > If this kind of redeclaration is allowed, what would the expression > &class_name::member_name yield in such cases? If class_name is the base class, it's the function. If class_name is the derived class, it's the data member. > Is it legal or illegal to try to take the address of an overloaded > method or function using the '&' operator? Given a particular > overloaded function or method that you absolutely *must* get the > address of, is there any way of uniquely specifying a particular > one of the overloadings? Specifically, is the following allowed > (or will it ever be)? > > &class_name::overloaded_method_name(int,int) It's almost legal. For example, this works: struct X { void f(int); void f(double); }; main() { void (X::*fp)(double) = X::f; } However, it's illegal if I rewrite the declaration of fp this way: void (X::*fp)(double); fp = X::f; > Is it legal to try to take the address of an overloaded operator > for a given class (e.g. &my_class::operator+) even if that operator > may have both unary and binary forms, so long as only one of these > two forms is actually defined for the given class? The answer to this is similar to the previous one -- you can use an overloaded name as an initializer but usually not as an expression. For instance, the following is legal: struct X { X operator+(const X&); X operator+(); }; main() { X (X::*fp)(const X&) = X::operator+; } > Is it legal to declare a virtual method in a base class with a given > parameter profile and then to declare a (virtual or plain) method > with the same name but with a different parameter profile in a class > which is derived from the given class? (GNU G++ thinks this is > illegal). An example: > > class base { > public: > int method (int, int); > }; > > class derived : public base { > public: > int method (float, float); // is this an error? > }; Your example is legal, even if you insert `virtual' in the definition of base::method. However, because the signatures of base::method and derived::method are different, the two functions are effectively completely unrelated. You should get a warning about this, but it's legal if it's really what you want to do. > Is there any acceptable way of getting at the address of a vtable for > a given class. No -- at least no way that is guaranteed by the language definition or that I would personally consider acceptable. Some things are just not intended to be known. -- --Andrew Koenig ark@europa.att.com
diamond@diamond.csl.sony.junet (Norman Diamond) (04/13/89)
In article <9189@alice.UUCP> bs@alice.UUCP (Bjarne Stroustrup) very kindly answers most of the questions that were asked by Ron Guilmette. If Mr. Stroustrup has time, please kindly try to answer some of them again. >Is it legal for an "operator delete" to return anything other than >type "void"? >***> Yes. It can take an additional argument of type long (a size) What about the _return_ type? >If a method member is declared in a derived class, can it be >redeclared in a derived class as a data member? >***> No (assuming you mean in the same derived class). You can only > overload functions. Mr. Guilmette must have meant: If a method member is declared in a _base_ class, can it be redeclared in a derived class as a data member? (method member == member function) >If this kind of redeclaration is allowed, what would the expression >&class_name::member_name yield in such cases? >***> It isn't. Probably it is, when the preceding question is corrected. Isn't the rule the same, finding the most derived type in the class lattice? >Is it legal or illegal to try to take the address of an overloaded >method or function using the '&' operator? Given a particular >overloaded function or method that you absolutely *must* get the >address of, is there any way of uniquely specifying a particular >one of the overloadings? >***> Yes. See the reference manual section 8.9. Essentailly, you can > only take the address of an overloaded function if the context > uniquely identifies which version. How do you provide the context? Mr. Guilmette's suggestion (following) seems very reasonable. > Specifically, is the following allowed >(or will it ever be)? > > &class_name::overloaded_method_name(int,int) >***> no and no (that would be ambiguous with a call) It would not be ambiguous. & cannot be applied to the result of a call. More obviously, "int" cannot be an actual parameter of a call, only an expression can be, but this does not help when a function takes no parameters. ------ cut here and discard everything below this point. ------ >Can a union have public, private and protected parts? >Can a union contain member functions? Gee, I thought the most interesting unions are those of private parts, one of which is a ... Never mind. Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?
bs@alice.UUCP (Bjarne Stroustrup) (04/14/89)
Norman Diamond writes > In article <9189@alice.UUCP> bs@alice.UUCP (Bjarne Stroustrup) > very kindly answers most of the questions that were asked by > Ron Guilmette. If Mr. Stroustrup has time, please kindly try > to answer some of them again. > >Is it legal for an "operator delete" to return anything other than > >type "void"? > >***> Yes. It can take an additional argument of type long (a size) > What about the _return_ type? Sorry. I shouldn't try answering questions at the end of a long hard day. There is nothing in the language that prevents you from chosing a return type, though it seems that all current implementations require void*. The default operator delete() in the library is: void* operator delete(void*); void* operator delete(void*, long); where `long' will be replaced by `size_t' as part of the ANSIfication. > >If a method member is declared in a derived class, can it be > >redeclared in a derived class as a data member? > >***> No (assuming you mean in the same derived class). You can only > > overload functions. > Mr. Guilmette must have meant: > If a method member is declared in a _base_ class, can it be > redeclared in a derived class as a data member? I thought that was one of the other questions. The answer to this last question is, Yes, this is legal: struct A { int f(); }; struct B : A { int f; }; > (method member == member function) I forgot that humor should be pre- or suffixed by a :-) in this forum :-) But I was also making a semi-serious point. Referring to member functions as `methods' makes some people believe they have a semantics and/or implementation very similar to Smalltalk methods. That can cause confusion. Also, some people use `method' to refer to all member functions and others use `method' to refer to virtual functions only. Another source of confusion. > >If this kind of redeclaration is allowed, what would the expression > >&class_name::member_name yield in such cases? > >***> It isn't. > Probably it is, when the preceding question is corrected. Isn't > the rule the same, finding the most derived type in the class lattice? Yes, given the declarations above B::f the integer member B::f. A::f will give you the function. Please remember we are talking language definition here and not about style. I would hope that examples like these will remain rare in real code. > >Is it legal or illegal to try to take the address of an overloaded > >method or function using the '&' operator? Given a particular > >overloaded function or method that you absolutely *must* get the > >address of, is there any way of uniquely specifying a particular > >one of the overloadings? > >***> Yes. See the reference manual section 8.9. Essentailly, you can > > only take the address of an overloaded function if the context > > uniquely identifies which version. > How do you provide the context? Mr. Guilmette's suggestion (following) > seems very reasonable. It IS very reasonable, but I did give an alternative, and Andy Koenig in a separate message gave an example of its use. Here is another example: void f(); void f(int); // ... void (*pv)() = &f; // gets void f(); void (*pi)(int) = &f; // gets void f(int); > > Specifically, is the following allowed > >(or will it ever be)? > > > > &class_name::overloaded_method_name(int,int) > >***> no and no (that would be ambiguous with a call) > It would not be ambiguous. & cannot be applied to the result of a > call. More obviously, "int" cannot be an actual parameter of a call, > only an expression can be, but this does not help when a function > takes no parameters. You are right. One could key the analysis on the `int'. This would make the syntax analysis of C++ even more horrid than it already is, but the main point is that C++ already has a mechanism for expressing this so why add mechanism? > ------ cut here and discard everything below this point. ------ > > >Can a union have public, private and protected parts? > >Can a union contain member functions? > > Gee, I thought the most interesting unions are those of private parts, > one of which is a ... > Never mind. I think C++ is an even better source of silly puns and jokes than C is :-)
rfg@riunite.ACA.MCC.COM (Ron Guilmette) (04/15/89)
In article <10161@socslgw.csl.sony.JUNET> diamond@diamond.csl.sony.jp (Norman Diamond) writes: >In article <9189@alice.UUCP> bs@alice.UUCP (Bjarne Stroustrup) >very kindly answers most of the questions that were asked by >Ron Guilmette. If Mr. Stroustrup has time, please kindly try >to answer some of them again. Yes please. > >>Is it legal for an "operator delete" to return anything other than >>type "void"? >>***> Yes. It can take an additional argument of type long (a size) >What about the _return_ type? Ditto! >>If a method member is declared in a derived class, can it be >>redeclared in a derived class as a data member? >>***> No (assuming you mean in the same derived class). You can only >> overload functions. >Mr. Guilmette must have meant: >If a method member is declared in a _base_ class, can it be >redeclared in a derived class as a data member? Right. I did make a mistake in phrasing my question. What I did mean (and what Mr. Diamond correctly realized) was: is the following legal: class base { public: int member (int i); base (); }; class derived : public base { public: int member; // legal ?? derived (); }; int test () { derived derived_object; &dervied::member; // what does this mean? &derived_object.member // what does this mean? } >>Is it legal or illegal to try to take the address of an overloaded >>method or function using the '&' operator? Given a particular >>overloaded function or method that you absolutely *must* get the >>address of, is there any way of uniquely specifying a particular >>one of the overloadings? >>***> Yes. See the reference manual section 8.9. Essentailly, you can >> only take the address of an overloaded function if the context >> uniquely identifies which version. >How do you provide the context? Mr. Guilmette's suggestion (following) >seems very reasonable. >> >> &class_name::overloaded_method_name(int,int) >>***> no and no (that would be ambiguous with a call) I don't see any problem with disambiguating such a notation and allowing the compiler to conclude that this is (obviously) a "name" of a particular overloaded function. After all, one look at the "actual parameters" and the compiler should be able to see that these are TYPES and not VALUES. Anyway, this is not a terribly important issue because there is a way (that I have just learned about from Stroustrup's reply above) to get the address of a particular overloading of a function. Unfortunately, the wording of section 8.9 of the reference manual leaves something to be desired when it comes to spelling out precisely what sorts of context information may or may not be used to disambiguate an overloaded function name when the & operator is applied to it. I have found through experimentation that the GNU g++ compiler does do disambiguation of overloaded function names in many cases which are not spelled out in the Reference Manual. Specifically, it seems to take into account: a) the type of the pointer being assigned to (or initialized) b) the type to which the value yielded by the & operator is (explicitly) casted, c) the type expected for the given actual function parameter (when the value yielded by the & operator is passed as an actual parameter to a function. Are all these possible disambiguation factors "legal" for a "standard conforming compiler" to take into account when performing disambiguation of overloaded function names? Are there any others? Note that when factor (c) above is used for disambiguation by the GNU g++ compiler, it is apparently possible for truly ambiguous things to slip by without any errors being generated, e.g.: ----------------------------------------------------------------------- overload function; overload function_of_function; void function (char c); void function (float f); typedef void (*ptr_to_function_of_char)(char); typedef void (*ptr_to_function_of_float)(float); void function_of_function (ptr_to_function_of_float); void function_of_function (ptr_to_function_of_char); int test () { function_of_function (function); // ERROR - ambiguous } ----------------------------------------------------------------------- What does cfront 2.0 do with this? -- // Ron Guilmette - MCC - Experimental Systems Kit Project // 3500 West Balcones Center Drive, Austin, TX 78759 - (512)338-3740 // ARPA: rfg@mcc.com // UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg