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?