Seems a bug of member access in a default template-argument

Viewed 188

Consider such two variance examples

Example #1

struct A{
    template<class T, int R>
    friend void show();

private:
    int c;
};

template<class T, int R = decltype(T{}.c){0} >
void show(){
}

int main(){
  show<A>();
}

Example #2

struct A{
    template<class T, int R>
    friend void show();

private:
    int c;
};

template<class T, int R = decltype(A{}.c){0} >
void show(){
}

int main(){
    show<A>();
}

Clang accepts #2 and rejects #1:


<source>:14:3: error: no matching function for call to 'show'
  show<A>();
  ^~~~~~~
<source>:10:6: note: candidate template ignored: substitution failure [with T = A, R = 0]: 'c' is a private member of 'A'
void show(){
     ^
1 error generated.
ASM generation compiler returned: 1
<source>:14:3: error: no matching function for call to 'show'
  show<A>();
  ^~~~~~~
<source>:10:6: note: candidate template ignored: substitution failure [with T = A, R = 0]: 'c' is a private member of 'A'
void show(){
     ^

However, according to [class.access.general] p9 and [class.access.general] p6, such two examples should all be well-formed

Access for a default template-argument ([temp.param]) is checked in the context in which it appears rather than at any points of use of it.

All access controls in [class.access] affect the ability to name a class member from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification.

Since the template function show is a friend of class A, hence the private member of A is also accessible in the part preceding the name of the entity(show) being declared, and the access of the default template-argument is checked in this context where it appears. It should be all fine. Is any rule that has an otherwise specification? If not, Is it considered a bug of Clang?

0 Answers
Related