【发布时间】:2020-01-28 23:14:26
【问题描述】:
为了一些全局函数
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 抱怨“在主模板声明中无效使用模板 ID 'func'”,那么我如何为每个 count 声明 func<T, count> 是 Obj<T> 的朋友?根据this answer,我只需要用这个替换朋友声明
template<typename T1, int count>
friend void func (const Obj<T1>& obj);
据我所知,无论T1 和T 是否匹配,这将使func<T1, count> 成为Obj<T> 的朋友,这是荒谬的。是否可以将func<T, count> 声明为Obj<T> 的朋友,而不是其他Obj<T1>? (最好将func<T, count>的定义保持在Obj<T>的定义之外)
(我知道我可以让count 成为一个真正的参数,但上面的示例只是对我的真实代码的简化。实际上,我试图以某种方式为某些类Obj<T> 重载std::basic_ostream<CharT, Traits>& operator<< (std::basic_ostream<CharT, Traits>& stream, const Obj<T>& obj)允许operator<< 访问Obj<T> 的私有字段。)
【问题讨论】:
-
您不需要两个前向声明中的任何一个(类
Obj或函数func)。相反,函数的friend声明将自己充当前向声明。 -
不能只在类中定义函数吗?