cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[namespace.udecl] How can we use the term "names a constructor" when a constructor doesn't have a name #498

Closed ranaanoop closed 4 months ago

ranaanoop commented 5 months ago

Full name of submitter: Anoop Rana

Reference (section label): [namespace.udecl]

Issue description:

The phrase "names a constructor" is used multiple times(6) in [N4950] but since constructors do not have names(class.ctor.general), this phrase do not make much sense.

For example, the note in namespace.udecl says:

[Note 2: Since destructors do not have names, a [using-declaration] cannot refer to a destructor for a base class. — end note]

But the same thing applies to constructors(class.ctor.general) and so if destructors not having names implies that a using-declaration cannot refer to a destructor for a base class, the same should be true for constructors.


namespace.udecl also states:

If the using-declarator names a constructor, it declares that the class inherits the named set of constructor declarations from the nominated base class..

Similarly, there are other uses of the phrase like in class.qual:

if N is dependent and is the terminal name of a using-declarator ([namespace.udecl]) that names a constructor,

cpplearner commented 5 months ago

[namespace.udecl]:

If the terminal name of the using-declarator is dependent ([temp.dep.type]), the using-declarator is considered to name a constructor if and only if [...].

[class.qual]:

In a lookup for a qualified name N whose lookup context is a class C in which function names are not ignored, if [...], N is instead considered to name the constructor of class C.

IIUC these are supposed to define what "name a constructor" means. Maybe they should be rephrased to look more like a definition?

ranaanoop commented 5 months ago

Maybe they should be rephrased to look more like a definition?

@cpplearner Yeah but note that the specific part of the quote namespace.udecl#1 you provided is talking about "dependent" terminal name case but in a example such as struct A{A(int);}; struct B: public A{using A::A;};, the terminal name is not dependent so the specific part of the quote(namespace.udecl#1) you mentioned doesn't apply.

But I did find basic.general.lookup#3 that seems to talk about "not dependent" terminal name case:

If any such declaration is a using-declarator whose terminal name ([expr.prim.id.unqual]) is not dependent ([temp.dep.type]), it is replaced by the declarations named by the using-declarator ([namespace.udecl])..

But the part "replaced by the declarations named by the using-declarator" in the above quote seems odd/cyclic to me.

ranaanoop commented 5 months ago

Additionally perhaps the non-normative note namespace.udecl#4.sentence-1 can be removed/revised.

cpplearner commented 5 months ago

using A::A; is subject to [class.qual]/1. A::A is a injected-class-name, and [class.qual]/1 says it's considered to name the constructor of A.

jensmaurer commented 4 months ago

"X having a name" and "to name a constructor" are distinct concepts in C++. [class.qual] seems rather explicit when we "name a constructor". I'm not seeing a core issue here.