cplusplus / cplusplus/draft

When does the lookup perform for a name used in default member initialization in a class template CWG1396

Open
#4,585 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

cwg not-editorial
Dominant language
TeX
Stars
221
Forks
813
Avg merge
16h 4m
Merged PRs (30d)
36

Description

This is also an issue that I recently asked on SO(https://stackoverflow.com/questions/67086569/how-does-the-lookup-rule-apply-to-a-name-that-is-used-in-a-default-member-initia). It seems no one can use the current wording to interpret this issue. In simple, the issue is:

#include <iostream>
template<class T>
struct A{
    int c = T::a;
};
struct B{
    A<B> cc;
    static const int a = 0;
};
int main(){

}

The definition of cc would cause the implicit specialization for A<B>, which in turn would cause the name lookup for T::a.

The declaration set is the result of a single search in the scope of C for N from immediately after the class-specifier of C if P is in a complete-class context of C or from P otherwise. If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.

According to the above code, we consider the P is not in the complete context of B, hence the member a of B cannot be found at this point. However, major implementations all accept the above example(GCC and Clang). The relevant rule of performing the lookup for a dependent name that appears in template entity is defined as:

If the name is dependent (as specified in [temp.dep]), it is looked up for each specialization (after substitution) because the lookup depends on a template parameter.

It's vague here. I infer that the name lookup for T::a might be in the definition context of the constructor of the specialization of template class A. such that could interpret the behavior of these compilers. This is hinted at in the following rule:
[class.base.init#9]

In a non-delegating constructor, if a given potentially constructed subobject is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then

if the entity is a non-static data member that has a default member initializer ([class.mem]) and either
the entity is initialized from its default member initializer as specified in [dcl.init];

However, it's not explicit. I think we should give an explicit rule for when does the name lookup perform for the name in such a case.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the supplied C++ example and compare the lookup rules in [temp.dep] with the cited [class.base.init#9] wording and CWG1396. Determine how lookup for T::a is intended to occur in this default member initializer, then clarify the draft wording so the example's accepted behavior and lookup timing are explicit.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.