Description
Consider this example
struct Base{
virtual void show(){} // #1
};
struct Derived: Base{
void show(this Base bptr){} // #2
};
According to [basic.scope.scope] p1, #1
corresponds to #2
as per [basic.scope.scope] p4 if their object parameters should be corresponding. [basic.scope.scope] p3 says that
Two non-static member functions have corresponding object parameters if:
- exactly one is an implicit object member function with no ref-qualifier and the types of their object parameters ([dcl.fct]), after removing top-level references, are the same, or
- their object parameters have the same type.
In this case, #1
and #2
satisfy the first bullet since the type of the implicit object parameter of #1
is Base&
while the type of the explicit object parameter of #2
is Base
, they have the same type after removing the top-level references. Hence, #2
can override#1
? Is it the intention after introducing deducing this?
If an explicit object member function can override an implicit object member function, it seems that the class type of the explicit object parameter must be the base class. Is it also the artificial intent?
Activity
[-][class.virtual] Overriding virtual fuction through an explicit object member function[/-][+][class.virtual] Overriding virtual function through an explicit object member function[/+]jensmaurer commentedon Dec 10, 2021
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html clearly says this about the intent:
So, it was originally intended that old-style and new-style member functions don't override each other.
However, since explicit/implicit member functions can now be used for redeclarations (not just overrides), this seems not obviously relevant anymore.
It seems to me the problem is that explicit-object member functions with a by-value parameter correspond to an implicit-object member function (which has a by-reference parameter). This may have calling convention impact, so is probably not desired. Example:
I think this should not be a redeclaration.
@brevzin , @opensdh , any thoughts?
jensmaurer commentedon Dec 10, 2021
I think my
C::f
example is misguided; those declarations correspond, but declare different entities, so this is ill-formed.I think we need a narrow fix for [class.virtual] that says that a virtual member function shall not be an explicit-object member function (or that only same-kind functions override). Or something like that.
brevzin commentedon Dec 10, 2021
We say they cannot be declared virtual here: http://eel.is/c++draft/dcl.dcl#dcl.fct-6
xmh0511 commentedon Dec 10, 2021
@brevzin Derived::show isn't declared virtual since the declaration contains no
virtual
specifier. be declared virtual is vague on its meaning that whether it is a virtual function or has avirtual
specifier on its declaration?jensmaurer commentedon Dec 10, 2021
@brevzin , unforunately, that's not quite sufficient, because "declared
virtual
" strongly hints that the keyword "virtual" actually appears on the declaration. With overriding, a function may be virtual without being so declared.I think we need "An explicit object member function shall not be virtual." in [class.virtual], then we can drop the "virtual" keyword prohibition in [dcl.fct] p6 and possibly replace it with a note.
xmh0511 commentedon Dec 10, 2021
@jensmaurer Hmmm, I would argue that
void C::f(this C)
andvoid C::f()
declare the same entity since they obey [basic.link] p8, I think the reason why they are ill-formed is stated by [basic.link] p11, that is, they declared the same entity but they have the different function type.jensmaurer commentedon Dec 10, 2021
Tangent: "corresponds" is not the right criterion to define "override": http://lists.isocpp.org/core/2021/12/11840.php
jensmaurer commentedon Mar 24, 2022
CWG2554
[-][class.virtual] Overriding virtual function through an explicit object member function[/-][+][class.virtual] Overriding virtual function through an explicit object member function CWG2554[/+]xmh0511 commentedon Mar 24, 2022
What is the purpose of "ignoring object parameters" in the proposed suggestion? Does it intend to say that just skip [basic.scope.scope] p3 when we check whether such two non-static member functions correspond where there is at least one explicit object member function? However, even if we ignore the object parameters(i.e. the implicit and explicit object parameters), they still are non-static member functions, which means
this rule still can work. If the wording means this intent, Is it better to say
7 remaining items