为什么允许嵌套类模板的部分特化,而完整不是?

template<int x> struct A { template<int y> struct B {};. template<int y, int unused> struct C {}; }; template<int x> template<> struct A<x>::B<x> {}; // error: enclosing class templates are not explicitly specialized template<int x> template<int unused> struct A<x>::C<x, unused> {}; // ok 

那么为什么不允许内部的,嵌套的类(或函数)的明确的专门化,如果外部类不专门呢? 奇怪的是,我可以解决这个问题,如果我只是通过简单地添加一个虚拟模板参数来部分专门化内部类。 使事情变得更丑陋,更复杂,但工作起来。

我认为完整的专业化是部分专业化的一个子集,尤其是因为你可以通过添加一个虚拟参数来expression每一个完整的专业化。 所以这个在部分专业化和完全专业化之间的歧义对我来说并不合适。

不幸的是,comp.std.c ++中没有人敢回答,所以我在这里再次带着赏金。

注意:我需要这个特性来为内部类的recursion模板提供一组外部类,内部参数的特化取决于外部模板参数。

我猜为什么发生这种情况:完整的专业化不再是“模板类/function”,它们是“真正的”类/方法,并获得真正的(链接器可见)符号。 但是对于部分专业模板中的完全专用模板,这不是事实。 可能这个决定只是为了简化编译器编写者的生活(并且在这个过程中使编码器变得更加困难:P)。

在第一种情况下,C ++标准明确禁止成员模板类的完全特化。 根据14.7.3 / 18:

在名称空间范围内出现的类模板或成员模板的成员的显式专门化声明中,成员模板及其一些封闭类模板可能保持未特定化 ,除非声明不明确地专门化类成员模板封闭类模板也没有明确的专门化

您可以通过将实际工作委托给另一个结构来解决此问题:

 namespace detail { template <class T, class U> struct InnerImpl {}; } template <class T> struct Outer { template <class U> struct Inner: detail::InnerImpl<T,U> { }; }; 

现在你可以按照你的意愿专门化InnerImpl

支持维吉尔的论点(他比我发表相同的理由更快),请考虑这一点:

 template<typename T1> class TOuter { public: template<typename T2> class TInner { public: T1 m_1; T2 m_2; }; }; template<typename T1> template<> class TOuter<T1>::TInner<float> { public: T1 m_1; float m_2; }; 

TInner是完全专业化的,还是因为T1而部分专业化?

编辑:

在考虑了一些其他的评论之后 – 你似乎希望根据外部类中的模板参数进行完整的特化。 如果你嵌套内部类的实现,这似乎在Visual Studio 2005中工作:

 template<typename T1> class TOuter { public: template<typename T2> class TInner { public: std::string DoSomething() { return "Inner - general"; } T2 m_2; }; template<> class TInner<T1> { public: std::string DoSomething() { return "Inner - special"; } T1 m_1; }; }; 

TOuter :: TInner将正确地成为TInner的专业化。 我无法用模板之外的实现来编译它。