Чтобы какая-то глобальная функция
template<typename T, int count>
void func (const Obj<T>& obj) {
for (int i = 0; i < count; i++)
std::cout << obj.value << std::endl;
}
могла получить доступ к закрытому полю value
некоторого шаблонного класса
template<typename T>
class Obj {
public:
Obj (T value);
private:
T value;
};
template<typename T>
Obj<T>::Obj (T value) : value(value) {}
, нам нужно объявить func<T, count>
друг Obj<T>
.Но func<T, count>
должен быть объявлен прежде, чем мы сможем сделать его другом Obj<T>
, и для этого нам нужно заранее объявить Obj<T>
.Результирующий код выглядит следующим образом:
// 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;
}
Но это заставляет gcc жаловаться на «недопустимое использование идентификатора шаблона 'func' в объявлении основного шаблона», так как же я на самом деле объявляю func<T, count>
другом?Obj<T>
для каждого count
?Согласно этому ответу Мне просто нужно заменить объявление друга на
template<typename T1, int count>
friend void func (const Obj<T1>& obj);
Насколько я знаю, это сделает func<T1, count>
другом Obj<T>
независимо от того, T1
и T
совпадают, что абсурдно.Можно ли объявить func<T, count>
другом Obj<T>
и никаким другим Obj<T1>
?(желательно таким образом, чтобы определение func<T, count>
не входило в определение Obj<T>
)
(я знаю, что мог бы просто сделать count
реальным параметром, но приведенный выше пример является просто упрощениеммой настоящий код. В действительности я пытаюсь перегрузить std::basic_ostream<CharT, Traits>& operator<< (std::basic_ostream<CharT, Traits>& stream, const Obj<T>& obj)
для некоторого класса Obj<T>
таким образом, чтобы operator<<
мог получить доступ к приватным полям Obj<T>
.)