What is an "identifier associated by name lookup"? - c++

So I was reading this para from C++ standard
14.6.2.2 [temp.dep.expr]/3
An id-expression is type-dependent if it contains
an identifier associated by name lookup with one or more declarations declared with a dependent type,
...
Can anyone explain what exactly the term means "an identifier associated by name lookup" ? , is it talking about ADL or something?

It means an identifier that, after name lookup has been performed, is now associated with one or more declarations of that name. Think of it as a one-to-many map of a name to a set of declarations that it could be referring to. When there's more than one associated declaration (e.g. function overloads), overload resolution is performed only after name lookup (and association) has been performed.
Now, as for what you quoted. A dependent type means a type that depends on the current template instantiation. So, for example, if we have
template<class T> struct A {
A<T> a1; // A<T> is a dependent type
A<T*> a2; // A<T*> is not a dependent type
};
In the example above, the reason A<T> is dependent is because it refers to the current instantiation of the template class. But A<T*> refers to a different instantiation—a whole other class.
So your quote basically goes to say that if you have an identifier in your template code that's associated with some declaration using a dependent type, then the id-expression containing it is type-dependent itself. That is, it refers to type(s) referring to the current instantiation.

Related

What is the definition of "dependent name" in C++?

In C++, the concept of dependent names is important because:
Such names are unbound and are looked up at the point of the template instantiation ... in both the context of the template definition and the context of the point of instantiation
However, the only thing that the standard says is a dependent name is given in [temp.dep]/2, referring to unqualified function calls, basically in order to enable ADL to be fully effective for those function calls.
Are there any other dependent names besides those?
Consider some code like this, for example:
template <class T>
void foo(T t) {
t.bar();
};
If one were to refer to bar as a "dependent name", would that be a technically incorrect use of the term, according to the standard?
Thanks to Declarations and where to find them being accepted into C++23, there is now an explicit enumeration of categories of dependent names, which seems to cover the code in the question.
In N4919 [temp.dep.general]/2 it is stated that
[...] The component name of an unqualified-id (7.5.4.2) is dependent if
it is a conversion-function-id whose conversion-type-id is dependent, or
it is operator= and the current class is a templated entity, or
the unqualified-id is the postfix-expression in a dependent call.
And in [temp.dep.type]/5 the rules for when qualified names are dependent are given:
A qualified name (6.5.5) is dependent if
it is a conversion-function-id whose conversion-type-id is dependent, or
its lookup context is dependent and is not the current instantiation, or
its lookup context is the current instantiation and it is operator=, or
its lookup context is the current instantiation and has at least one dependent base class, and qualified name lookup for the name finds nothing (6.5.5).
Regarding the example of t.bar() given in the question, the name bar is described in the referenced section (6.5.5) ([basic.lookup.qual]) as a "member-qualified-name". Furthermore, [basic.lookup.qual]/2 explains that its "lookup context" is "the type of its associated object expression (considered dependent if the object expression is type-dependent)". Clearly t is type-dependent, and it is the lookup context for bar, so [temp.dep.type]/5.2 applies, and bar is indeed a dependent qualified name.

Name lookup in template base: why do we add this->

Consider the following:
struct Base {
void foo();
};
template <class T>
struct Derived : Base {
void bar() {
this->foo();
}
};
Typically, we explain that this-> makes foo() a dependent name, so its lookup is posponed to the second phase, i.e. to the template instantiation point.
But the second phase lookup invokes only ADL, which does not consider member functions, does it?
I'd appreciate any pointer to the Standard paragraph that explains why the above code compiles.
But the second phase lookup invokes only ADL, which does not consider member functions, does it?
It does not. However ADL adds to the lookup set, it does not comprise all of it. Also, the idea you are paraphrasing here applies to a postfix-expression in postfix-expression(args), when said postfix-expression is an unqualified-id.
[temp.dep]
1 ... In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an unqualified-id, the unqualified-id
denotes a dependent name if
[... specific conditions ...]
If an operand of an operator is a type-dependent expression, the
operator also denotes a dependent name. Such names are unbound and are
looked up at the point of the template instantiation ([temp.point]) in
both the context of the template definition and the context of the
point of instantiation.
So if you had there foo() instead, lookup would not consider members, and would instead try only free functions, both at the point of definition and instantiation (where ADL can add to the lookup set, assuming we had a dependent expression).
But for this->foo (I omitted the call intentionally, to discuss the postfix-expression), we have class member access. And here other paragraphs apply:
[temp.dep.type]
5 A name is a member of the current instantiation if it is
[...]
An id-expression denoting the member in a class member access expression for which the type of the object expression is the current instantiation, and the id-expression, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof. [ Note: If no such member is found, and the current instantiation has any dependent base classes, then the id-expression is a member of an unknown specialization; see below.  — end note ]
6 A name is a member of an unknown specialization if it is
[...]
An id-expression denoting the member in a class member access expression in which either
the type of the object expression is the current instantiation, the current instantiation has at least one dependent base class, and name
lookup of the id-expression does not find a member of a class that is
the current instantiation or a non-dependent base class thereof; or
7 Similarly, if the id-expression in a class member access expression for which the type of the object expression is the current instantiation does not refer to a member of the current instantiation or a member of an unknown specialization, the program is ill-formed even if the template containing the member access expression is not instantiated; no diagnostic required.
These bullets tell us what lookup to perform when this->foo is encountered. It looks up members only. In our case, we have a non-dependent base class in the current instantiation, so that's where the member is to be found, unambiguously.
Having found the member function, the postfix-expression this->foo denotes a callable, and that is how the function call is resolved.
The phrase “two-phase lookup” is widely misunderstood, even among experts. C++17 said both
Such names are unbound and are looked up at the point of the template instantiation (17.6.4.1) in both the context of the template definition and the context of the point of instantiation.
(in [temp.dep]/1) and
In resolving dependent names, names from the following sources are considered:
— Declarations that are visible at the point of definition of the template.
— Declarations from namespaces associated with the types of the function arguments both from the
instantiation context (17.6.4.1) and from the definition context.
(in [temp.dep.res]/1), each of which seems to suggest that these are the two phases. However, a better way of interpreting this (unofficial) phrase is that lookup is done
from the template definition: for non-dependent names
during instantiation: from the definition but also, via ADL only, from the instantiation context
The former can be done when parsing the template definition, but no diagnostic is required for uninstantiable templates ([temp.res]/8). Note that the latter includes more than ADL.
The relevant wording has been clarified recently; it now merely says
[Note: For the part of the lookup using associated namespaces ([basic.lookup.argdep]), function declarations found in the template instantiation context are found by this lookup, as described in [basic.lookup.argdep]. — end note]
as a reminder of the difference in the second phase. Nonetheless, it confusingly uses dependent name only to refer to unqualified dependent names/operators ([temp.dep]/2). Names like Derived::foo (from the this->) are clearly dependent; as qualified names, they’re not subject to ADL, but they are still looked up during instantiation—which allows results from a dependent base to be found. (Your example has a non-dependent base, but that’s available then too.)

C++ lookup for dependent names

In the current C++ standard (march 2019), there are these two paragraphs (emphasis mine):
[temp.res] p.2:
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename. [...]
[temp.res] p.9:
When looking for the declaration of a name used in a template definition, the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) are used for non-dependent names. The lookup of names dependent on the template parameters is postponed until the actual template argument is known ([temp.dep]). [...]
The first paragraph implies that a name that is dependent on a template parameter will be looked up by "the applicable name lookup".
However, the second paragraph states that lookup for names dependent on template parameters is postponed until the template argument is known.
The example that is part of the first paragraph includes a situation similar to the following one:
template <typename T>
class A
{
void f()
{
T* p;
}
};
In method f, I believe T is a "name dependent on template parameters", therefore its lookup should be postponed until T is known, therefore there is no "applicable name lookup", the name should be assumed not to name a type.
What does the first quoted paragraph mean by "unless the applicable name lookup finds a type name", if the second quoted paragraph seems to state that there is no lookup performed? Am I missing something?
Thank you.
The lookup that is postponed is for dependent names: for example, foo in contexts like T::foo or Bar<T>::foo, or operator# in contexts like T() # 0. Obviously T and Bar must themselves be looked up just to know a template parameter is involved (template parameters can be hidden) and to parse the template argument list. Since a (type) template parameter is a typedef-name and any specialization of Bar is a type, that “name lookup finds a type name”.

Why is template function of data member a dependent name only when qualifying with "this"?

struct Bar {
template<typename>
void baz() {
}
};
template<typename>
struct Foo {
Bar bar;
Foo() {
bar.baz<int>();
}
};
int main() {
return 0;
}
This code compiles fine (in GCC 4.7), but if I prefix the call to bar.baz<int>() with this->, baz becomes a dependent name that needs disambiguating with template.
bar.baz<int>(); // OK
this->bar.baz<int>(); // error
this->bar.template baz<int>(); // OK
Surely this->bar can only refer to Bar bar, whose member baz is clearly a template? Why does the addition of this-> make this code ambiguous to the compiler?
p.s. Originally, bar was a data member of a base class template which needed disambiguating with this->, but I have simplified the example for the purpose of this question.
this->bar.baz<int>(); // error
The statement above, within the definition of template<typename T> Foo<T>::Foo(), is well-formed, and should be accepted if C++11 mode or C++1y mode is enabled. But it was technically ill-formed according to C++03.
Both standards agree that this is a type-dependent expression:
C++03 14.6.2.1/1; N3690 14.6.2.1/8:
A type is dependent if it is
a template parameter,
...
a [simple-]template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent,
[T is a dependent type, and so is Foo<T>.]
C++03/N3690 14.6.2.2/2:
this is type-dependent if the class type of the enclosing member function is dependent.
[Since Foo<T> is a dependent type, the expression this in its member definition is type-dependent.]
Both standards begin 14.6.2.2 with:
Except as described below, an expression is type-dependent if any subexpression is type-dependent.
C++03 has only three simple categories of expressions with more exact descriptions:
Primary expressions (this and looked-up names)
Expressions that specify their own type (like casts and new-expressions)
Expressions with constant type (like literals and sizeof).
The first category is defined in C++03 14.6.2.2/3:
An id-expression is type-dependent if it contains:
an identifier that was declared with a dependent type,
a template-id that is dependent,
a conversion-function-id that specifies a dependent type,
a nested-name-specifier that contains a class-name that names a dependent type.
So the lone expression bar is not dependent: it is an identifier and an id-expression, but none of the above apply.
But this->bar is not an id-expression, or in any of the other C++03 exceptions, so we have to follow the subexpression rule. Since subexpression this is type-dependent, the containing expression this->bar is also type-dependent.
But in fact, as you noticed, the type of this->bar can be known while parsing the template definition, without instantiating any template arguments. It is declared as a member of the primary template, so the name must bind to that member declaration. A template specialization might make Foo<T>::bar undeclared or declared in a different way, but in that case the primary template won't be used at all and the current definition of Foo() is ignored for that specialization. Which is why C++11 defined the concept of "the current instantiation" and used it for a further exception to the contagiousness of type-dependent expressions.
N3690 14.6.2.1/1:
A name refers to the current instantiation if it is
in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class
in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in <> (or an equivalent template alias specialization),
...
[The first bullet says Foo is the current instantiation. The second says Foo<T> is the current instantiation. In this example, both name the same type.]
14.6.2.1/4:
A name is a member of the current instantiation if it is
An unqualified name that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
A qualified-id in which ...
An id-expression denoting the member in a class member access expression for which the type of the object expression is the current instantiation, and the id-expression, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
[The first bullet says bar alone is a member of the current instantiation. The third bullet says this->bar is a member of the current instantiation.]
Finally, C++11 adds a fourth category of rules for type-dependent expressions, for member access. 14.6.2.2/5:
A class member access expression is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization.
this->bar does refer to a member of the current instantiation, but the type Bar of the referenced member is not dependent. So now this->bar is not type-dependent, and the name baz in this->bar.baz is looked up during the template definition as a non-dependent name. The template keyword is not needed before baz.
Short summary
This is just the way the current C++11 rules are: this->bar.baz<int>() introduces a dependent name not in the current instantiation context that requires disambiguation with the template keyword, even though it is very hard to come up with an actual example of a competing parse that change the semantics of the expression this->bar.baz<int>().
Parsing ambiguity from angle brackets
First: why in general is there a need for template?
When a C++ compiler encounters an expression f<g>(0), it can interpret this either as "call the function template f for template argument g and function argument 0 and evaluate the result" or it can mean "make the comparison (f<g)>(0) for names f and g and constant 0." Without further information it cannot make this decision. This is an unfortunate consequence of the choice of angle brackets for template arguments.
In many (most) cases, the compiler does have enough context to decide whether a template expression or a comparison is being parsed. However, when a so-called dependent name (essentially a name that is explicitly or implicitly dependent on a template parameter of the current scope) is encountered, another language subtlety comes into play.
Two-phase name lookup
Because a name dependent on a template could change its meaning (e.g. through specializations) when a template is being instantiated for a concrete type, name lookup of dependent names is done in two phases (quote from C++ Templates the Complete Guide):
During the first phase, nondependent names are looked up while the
template is being parsed using both the ordinary lookup rules and, if
applicable, the rules for argument-dependent lookup (ADL).
Unqualified dependent names (which are dependent because they look like the name of a function in a function call with dependent
arguments) are also looked up that way, but the result of the lookup
is not considered complete until an additional lookup is performed
when the template is instantiated.
During the second phase, which occurs when templates are instantiated
at a point called the point of instantiation (POI), dependent
qualified names are looked up (with the template parameters replaced
with the template arguments for that specific instantiation), and an
additional ADL is performed for the unqualified dependent names.
Why this-> makes your code different
Using this-> inside a class template introduces a dependent name and triggers two-phase name lookup. In that case, the rule cited by #40two comes into play. The point is that the ADL at the 2nd phase can bring in new names from explicit specializations that redefine the meaning of your bar and baz and it could conceivably change the meaning of this->bar.baz<int>(0) to a comparison rather than a function template call.
Granted, for non-type template arguments such as this->bar.another_baz<0>() this would be more likely than for a type template parameter. In this related Q&A a similar discussion arose whether one could find a syntactic valid form that changes the meaning of this->f<int>() vs this->template f<int>(0), without a clear conclusion.
Note that C++11 already relaxes the rule for template disambiguation compared to C++98. Under the current rules this->f<int>() for a template<class> f() inside Foo would not require template because it is in the so-called current instantiation. See this answer from the canonical Q&A for this topic for more details
According to the standard § 14.2/4 Names of template specializations [temp.names]
When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template.
Edit:
Also, according the standard § 14.6.2.2/2 Type-dependent expressions [temp.dep.expr]:
this is type-dependent if the class type of the enclosing member function is dependent (14.6.2.1).
Thus, in order to call bar.baz<int>() via this you need to prefixed by the keyword template:
this->bar.template baz<int>();
LIVE DEMO
[Reason:]
The compiler needs this "redantant" use of template keyword, because it can't decide whether the token < is operator< or the beginning of a template argument list.

Should name lookup be deferred for a dependent class/namespace-name in a class-member-access expression?

The following code is rejected by both clang and gcc
template<typename T>
void f(T t)
{
t.Dependent::f(); // clang accepts, gcc rejects
t.operator Dependent*(); // both reject
}
struct Dependent
{
void f();
};
struct A : Dependent
{
operator Dependent*();
};
template void f<A>(A);
My reading of the standard suggests both expressions should be accepted.
In both cases, Dependent can only be a type name.
In both cases, the name Dependent is to be "looked up in the class of the object expression" t. As t is a type-dependent expression, the lookup should be deferred until the template is instantiated.
Is there something I'm missing?
EDIT: If it is intended that such a name is not dependent, what is the rationale for this decision? I can see that it makes life easier for the implementor if they do not have to defer evaluation of a construct like t.operator X::Dependent* or t.X::Dependent::f where X could be either a namespace or a type name. I'm not clear on whether this is an intended or unintended side-effect of the current wording.
Relevant quotes from C++ Working Draft N3337:
3.4.5 Class member access [basic.lookup.classref]
If the id-expression in a class member access is a qualified-id of the form
class-name-or-namespace-name::...
the class-name-or-namespace-name following the . or -> operator is first looked up in the class of the
object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire
postfix-expression. [ Note: See 3.4.3, which describes the lookup of a name before ::, which will only find a
type or namespace name. —end note ]
If the id-expression is a conversion-function-id, its conversion-type-id is first looked up in the class of the
object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire
postfix-expression. In each of these lookups, only names that denote types or templates whose specializations
are types are considered.
14.6.2 Dependent names [temp.dep]
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such a
construct depends on the template parameters. In particular, types and expressions may depend on the type
and/or value of template parameters (as determined by the template arguments) and this determines the
context for name lookup for certain names. Expressions may be type-dependent (on the type of a template
parameter) or value-dependent (on the value of a non-type template parameter).
[...]
Such names are unbound and are looked up at the point of the template instantiation (14.6.4.1) in both the
context of the template definition and the context of the point of instantiation.
14.6.2.1 Dependent types [temp.dep.type]
A name is a member of an unknown specialization if it is
[...]
— An id-expression denoting the member in a class member access expression (5.2.5) in which either
— the type of the object expression is the current instantiation, the current instantiation has at least
one dependent base class, and name lookup of the id-expression does not find a member of the
current instantiation or a non-dependent base class thereof; or
— the type of the object expression is dependent and is not the current instantiation.
[...]
A type is dependent if it is
— a member of an unknown specialization,
1
Here is how I think your first case, t.Dependent::f works. First, I believe (means, I am not totally sure) that 14.6.2.1p5 should say "unqualified-id" instead of "id-expression". But independent of that, your name Dependent::f is actually composed out of two names (in the Standard, each nested nested-name-specifier followed by a member name is called "qualified-id", even if grammatically, these are not qualified-id productions. So a name foo::bar::baz is a qualified-id but also contains 1 other "qualified-id" aswell).
Dependent and Dependent::f. The former is not "An id-expression denoting the member in a class member access expression", so you can't simply apply the rule that applies to Dependent::f to apply also to Dependent.
Dependent is therefor non-dependent and albeit it will need to be looked up within a dependent type will have to be found at definition time. I personally think that we should have a clause that says "When looking up a qualified-id where the qualifier is type-dependent, name lookup yields an empty result.", to handle these "force name-lookup to be done immediately" gracefully. So anyway, in the end, I think your first case is ill-formed by not finding Dependent (clause 3.4 can't just decide by itself over the head of clause 14 that the name is actually dependent anyway).
2
For your other case, operator Dependent, things are easier. You again have two names, Dependent and operator Dependent. Again, I found nothing that says that Dependent is a dependent name here (I am not sure whether that would be wrong or not. That's beyond me).
Name lookup comparison (say, the equality function of the name lookup hash table) for operator function names is "they are conversion-function-ids formed with the same type" (3.8). This means that in order to form the name itself (not yet doing name lookup!), you not only have to give the lexical spelling as is the case for identifiers, but you have to provide a type identity, which needs to be provided by Dependent.
That the lookup of the dependent id-expression in t.operator Dependent* is delayed simply means that the semantic type comparison is delayed. Try this one, which should work fine
struct Dependent; // forward decl at global scope
t.operator Dependent*(); // in function template
Your followup
If it is intended that such a name is not dependent, what is the rationale for this decision? I can see that it makes life easier for the implementor if they do not have to defer evaluation of a construct like t.operator X::Dependent* or t.X::Dependent::f where X could be either a namespace or a type name.
I don't know the rationale, but I think you already have given a good point. This looks very much to the rule that skips dependent base classes when looking up unqualified names. And I think what rationale applies for that case applies for this case aswell. It makes it easier to reason on the function template for the programmer, especially.
struct Dependent;
template<typename T>
void f(T t)
{
t.Dependent::f();
t.operator Dependent*();
}
The code looks fine, but if T happens to have a Dependent member, suddenly Dependent would have a different binding (because first we are told to look into t's class, and then into the surrounding scope). Under my current understanding of the templating rules, the above always refers to the surrounding scope's Dependent, so the above code is "safe", regarding to that pitfall.