I want to make a single specialization a friend as shown below. I tried the following with C++20 but the program gets rejected by clang and is accepted by GCC and MSVC.
template <class T>
struct Ext {
struct Inner
{
int m{};
};
/*Is there a way to make this specialization work with all the compilers?
Note that I know that I can write template<typename S> friend void fun2(Ext<T>::Inner&)
but I only want to make this specialization a friend
*/
friend void fun2<T>(typename Ext<T>::Inner&); //C++20: works in gcc and msvc but rejected by clang
};
template <class T>
void fun2(typename Ext<T>::Inner &p)
{
p.m = 10;
}
int main()
{
Ext<int>::Inner x;
fun2<int>(x);
}
I have two questions:
Is there a way to make that specialization
void fun2<T>(typename Ext<T>::Inner&);a friend so that the program is accepted by all compilers? That is, I want a workaround for making this particular specialization a friend instead of allExt.Is the program shown above(in my post) well-formed in C++20?
Clang says:
<source>:13:16: error: no candidate function template was found for dependent friend function template specialization
13 | friend void fun2<T>(typename Ext<T>::Inner&); //C++20: works in gcc and msvc but rejected by clang
| ^
<source>:24:15: error: use of undeclared identifier 'x'
24 | fun2<int>(x);
It seems the program is ill-formed and gcc and msvc are wrong in accepting the program.
First note that
fun2<T>refers to a specialization of a function template. From temp.friend:Next, From temp.deduct.decl:
(emphasis mine)
And in our example, the set is empty and so there is no match which implies that the program is ill-formed as per the above quoted reference.