【发布时间】:2020-08-14 08:08:08
【问题描述】:
这是一个有点复杂的模式,不适合友谊。也许我必须重新考虑设计,但现在我只是对是否有可能完成这项工作感兴趣。问题是我不能声明我想在函数专业化声明中使用的 A 类模板显式实例化(使用不完整的 B 类作为模板参数),我想在 B 的定义中用作友元声明。
namespace ns
{
template<class ElemT>
void assem_elem(ElemT& elem);
template<class CompT>
class ElemTempl
{
public:
ElemTempl()
{
assem_elem(*this);
}
CompT comp;
};
namespace el { class Comp; }
template class ElemTempl<el::Comp>; // error: 'ns::ElemTempl<ns::el::Comp>::comp' uses undefined class 'ns::el::Comp'
using Elem = ElemTempl<el::Comp>;
template<> void assem_elem<Elem>(Elem& elem);
namespace el
{
class Comp
{
friend void ns::assem_elem<Elem>(Elem& elem);
void link(){}
};
}
template<> void assem_elem<Elem>(Elem& elem)
{
elem.comp.link();
}
}
int main()
{
ns::Elem el{};
return 0;
}
更新:
我想出了两个解决方案。首先,我可以删除
template class ElemTempl<el::Comp>;
线。下一行
using Elem = ElemTempl<el::Comp>;
似乎是实例化的声明(?)。另外,即使没有using 行我也可以写
template<> void assem_elem<ElemTempl<el::Comp>>(ElemTempl<el::Comp>& elem);
直接,这将起作用。但为什么?我不能在常规课程中做到这一点。至少我必须说类似<class RegularClass>,而不仅仅是<RegularClass>。
第二种解决方案是使用一个类并通过元素的模板参数传递它:
namespace ns
{
template<class CompT, class AssemT>
class ElemTempl
{
public:
ElemTempl()
{
AssemT{ *this };
}
CompT comp;
};
class Assem;
namespace el
{
class Comp
{
friend ns::Assem;
void link() {}
};
}
using Elem = ElemTempl<el::Comp, Assem>;
class Assem
{
public:
Assem(Elem& elem) { elem.comp.link(); }
};
}
但这里也有一些需要澄清的地方。类Assem 使用Elem,因此它实例化了Elem,但Elem 需要实例化Assem,而Assem 尚未定义。这怎么行?
【问题讨论】:
标签: c++ templates declaration friend incomplete-type