如何解决类模板显式实例化声明
这是一个有点复杂的模式,并不适合友谊。也许我不得不重新考虑设计,但是现在我只是对是否有可能进行这项工作感兴趣。问题是,我无法在要用作B定义中的朋友声明的函数特化声明中声明要使用的A类模板显式实例化(使用不完整的B类作为模板参数)。 / p>
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
。这怎么办?
解决方法
您似乎对explicit instantiation和template specialization感到困惑。
使用template class ElemTempl<el::Comp>;
(显式实例化),您可以实例化完整的类,而CompT comp;
需要完整的类型,而el::Comp
仅是向前声明的。
using Elem = ElemTempl<el::Comp>;
只是别名的定义。没有实例化。
template<> void assem_elem<Elem>(Elem& elem);
声明了特殊化,Elem
可能不完整。
类Assem使用Elem,因此它实例化Elem,但是Elem需要实例化Assem,并且尚未定义Assem。这怎么办?
Elem本身仅需要向前声明才有效。
该类在实例化时需要完整的类型el::Comp
。
构造函数ElemTempl::ElemTempl
在实例化时需要完整的Assem
。
构造类和方法时,不会隐式实例化,而构造类和方法是显式实例化。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。