Prev: Constrained name value pairs or pre-filled names types?
Next: So, it's not just ANY compile error that can be used with SFINAE.
From: DeMarcus on 10 May 2010 23:28 Hi, In �10.3/5 they explain covariant return types. Do they hold also for non-virtual functions? I.e. is this legal on all compilers according to the standard? struct A_helper { A& fnc(); }; struct B_helper { B& fnc(); }; struct A : A_helper { }; struct B : A, B_helper { }; The inheritance structure would look like this. A_helper / / A | | B_helper | / | / B So B would have both following A& fnc() B& fnc() Thanks, Daniel -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Chris Uzdavinis on 11 May 2010 17:06 On May 11, 9:28 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote: > Hi, > > In �10.3/5 they explain covariant return types. Do they hold also for > non-virtual functions? I.e. is this legal on all compilers according to > the standard? Covariant return type rules are irrelevant for nonvirtual functions. The situation you're describing is only subject to name lookup issues, and in particular, an ambiguity that arises when trying to call a function named fnc() on an object of type B. However, once a function is resolved (which would probably be through explicit qualification), then its validity undergoes the same consideration as any other normal function call would. Chris -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Joshua Maurice on 13 May 2010 03:36 On May 12, 1:06 am, Chris Uzdavinis <cuz...(a)gmail.com> wrote: > On May 11, 9:28 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote: > > > Hi, > > > In �10.3/5 they explain covariant return types. Do they hold also for > > non-virtual functions? I.e. is this legal on all compilers according to > > the standard? > > Covariant return type rules are irrelevant for nonvirtual functions. The > situation you're describing is only subject to name lookup issues, and in > particular, an ambiguity that arises when trying to call a function named > fnc() on an object of type B. However, once a function is resolved (which > would probably be through explicit qualification), then its validity > undergoes the same consideration as any other normal function call would. Let me explain a bit more. Let's first be clear on terminology. When a class has two different functions with the same name (and thus they have different signatures), the functions are said to "overload". When a derived class implements a function with the same signature as a function in one of its super types, that function is said to "override" the super's function. Let's talk about what virtual functions do. When you call a virtual function, you are not calling a specific function at a specific address. Instead, the following steps happen: 1- For the static type of the lvalue (which is probably a super class of some other type for exposition), do overload resolution on the name and arguments to pick the function signature. Note that return types do not affect function overload resolution. Return types are not part of function signatures. If it picks a function with a "bad" return type, the program is ill formed and the compiler does not try to "pick a better one". 2- Then, for the dynamic type of the object, aka most derived type, and for all of its super types, find all of the functions which have a matching signature. Again, return types are not part of a function's signature. If there exists a "most derived" function, then that function will be called. Otherwise the definition of the derived type should have a compile error. 3- That function is called. It has a return value. The caller expects the return value to be the return value of the function of the static lvalue object type, aka of the super type. However, the actual function called is (potentially) that of a derived type. A simple rule would be to simply require that the return type of an overrided function to be the same as the super's function. However, it makes sense, for a virtual function in the super class of return type pointer to T (or reference), to allow the actual function in the derived class to return a pointer (or reference) to a derived type of T. Ex: class A {}; class derived_from_A : public A {}; class B { public: virtual A* foo(); }; class derived_from_B : public B { public: virtual derived_from_A* foo(); }; When someone calls B::foo, he expects it to return a "A*", and specifically a pointer to some A object. However, if it returns a "A*" which actually points to a derived_from_A object, specifically the A sub-object of a derived_from_A object, then caller should be able to proceed. That is covariant return types. It is allowed a function override to have return type of a derived type of the return type of the function in the super class. Without virtual, there is no overriding, only overloading, and thus talking about covariant return types does not make sense. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alf P. Steinbach on 13 May 2010 08:39 On 11.05.2010 16:28, * DeMarcus: > Hi, > > In �10.3/5 they explain covariant return types. Do they hold also for > non-virtual functions? I.e. is this legal on all compilers according to > the standard? As noted else-thread the issue of covariant return types is irrelevant to your question. > struct A_helper > { > A& fnc(); > }; > > struct B_helper > { > B& fnc(); > }; > > struct A : A_helper > { > }; > > struct B : A, B_helper > { > }; > > The inheritance structure would look like this. > > A_helper > / > / > A > | > | B_helper > | / > | / > B > > So B would have both following > A& fnc() > B& fnc() That's OK. Until you try to /call/ fnc on a B object. At that point two declarations of fnc will be found in different base classes, and the compiler doesn't even consider the result types or anything (e.g. it doesn't check whether one of methods are const), it just has a clear ambiguity at hand. Cheers & hth, - Alf -- blog at <url: http://alfps.wordpress.com> [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alf P. Steinbach on 14 May 2010 00:49
* Joshua Maurice: > > Without virtual, there is no overriding, only > overloading, and thus talking about covariant return types does not > make sense. There is overriding, overloading and hiding, although one may use the word "overloading" to include the latter, and I suspect the standard does. But anyway, with hiding in the picture it does make sense to talk about covariant result types for non-virtuals. E.g., struct A { A& a() { return *this; } A& foo() const { return *this; } }; struct B: A { B& b() { return *this; } B& foo() const { return *this; } // Covariant result type } Now writing B().foo().b().a() should work nicely, but writing B().a().foo().b() should not compile. The first expression works because the result type of foo is covariant. The C++ limited support for virtual methods with covariant result types is an orthogonal issue. And invocation of that support is not what "covariant" means in general. That said, as you note, covariance has nothing to do with the OP's question. Cheers & hth., - Alf -- blog at <url: http://alfps.wordpress.com> [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |