This is the classical 'passkey' pattern which allows a function to be accessible only within the scope of a specific class:
#include <iostream>
template <typename T>
class passkey {
private:
friend T;
passkey() {}
// noncopyable
passkey(const passkey&) = delete;
passkey& operator=(const passkey&) = delete;
};
struct A {
A();
};
void g(int i, passkey<A>) {
std::cout << i;
}
A::A(){g(42,{});}
int main() {
A a;
return 0;
}
Here the funtion g can only be called within A. But is it possible to extend it if A is now a template class? The following snippet does not compile (with clang, but it works with gcc...), because for a template friend, it seems that one must use an elaborated-class-specifier, which seems to lead to a declaration conflict...
#include <iostream>
template <template<typename...> class T>
class passkey {
private:
template<typename...> friend class T;
passkey() {}
// noncopyable
passkey(const passkey&) = delete;
passkey& operator=(const passkey&) = delete;
};
template<typename T>
struct A {
A();
};
void g(int i, passkey<A>) {
std::cout << i;
}
template<typename T>
A<T>::A(){g(42,{});}
int main() {
A<void> a;
return 0;
}
This gives with clang:
>source>:6:38: error: declaration of 'T' shadows template parameter
template<typename...> friend class T;
^
<source>:3:39: note: template parameter is declared here
template <template<typename...> class T>
Is there any trick to have that work?