In order for some global function
template<typename T, int count>
void func (const Obj<T>& obj) {
for (int i = 0; i < count; i++)
std::cout << obj.value << std::endl;
}
to be able to access to the private field value of some templated class
template<typename T>
class Obj {
public:
Obj (T value);
private:
T value;
};
template<typename T>
Obj<T>::Obj (T value) : value(value) {}
we need to declare func<T, count> a friend of Obj<T>. But func<T, count> has to be declared before we can make it a friend of Obj<T>, and for this we need to forward-declare Obj<T>. The resulting code looks like this
// Forward declarations
template<typename T>
class Obj;
template<typename T, int count>
void func (const Obj<T>& obj);
// Obj<T>
template<typename T>
class Obj {
public:
Obj (T value);
template<int count>
friend void func<T, count> (const Obj<T>& obj);
private:
T value;
};
template<typename T>
Obj<T>::Obj (T value) : value(value) {} // <-- ERROR
// func<T>
template<typename T, int count>
void func (const Obj<T>& obj) {
for (int i = 0; i < count; i++)
std::cout << obj.value << std::endl;
}
But this makes gcc complain about the "invalid use of template-id 'func' in declaration of primary template", so how do I actually declare func<T, count> a friend of Obj<T> for every count? According to this answer I just need to replace the friend declaration with this
template<typename T1, int count>
friend void func (const Obj<T1>& obj);
As far as I know this would make func<T1, count> a friend of Obj<T> regardless of whether T1 and T match, which is absurd. Is it possible to declare func<T, count> a friend of Obj<T> and no other Obj<T1>? (preferably in a way that keeps the definition of func<T, count> outside the definition of Obj<T>)
(I know I could just make count a real parameter, but the example above is just a simplification of my real code. In reality I'm trying to overload std::basic_ostream<CharT, Traits>& operator<< (std::basic_ostream<CharT, Traits>& stream, const Obj<T>& obj) for some class Obj<T> in a way that allows operator<< to access private fields of Obj<T>.)