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

Gun*_*iez 42 c++ templates metaprogramming

    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
Run Code Online (Sandbox Code Playgroud)

那么,如果外部类也不是专用的,为什么不允许内部嵌套类(或函数)的显式特化?奇怪的是,如果我只是简单地添加一个虚拟模板参数来部分地专门化内部类,我可以解决这个问题.使事情更丑陋,更复杂,但它确实有效.

我会将完全特化视为部分特化的子集 - 特别是因为您可以通过添加伪参数将每个完整的特化表示为部分.因此,部分和完全专业化之间的消歧对我来说并没有多大意义.

不幸的是,没有人在comp.std.c ++敢于回答,所以我再次以赏金把它放在这里.

注意:我需要此功能用于一组外部类的内部类的递归模板,而内部参数的特化确实取决于外部模板参数.

Vir*_*gil 27

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

  • 这就是我在括号中开玩笑的原因.很明显,没有任何难以理解的事情,因为"它永远不会起作用,因为[...]",所以不允许它被禁止的最好的可能原因是"不要混淆用户".但考虑到n00b C++程序员可能会混淆多少其他方式,这将是有趣的:).我实际上发现C++在混淆不知情的新手和防止非常高级的程序员做有效(有时甚至是优雅)的工作方面做得非常出色,所有这些都是为了显而易见的实现细节.但那只是我的意见,当然:) (10认同)
  • 叹息......模板类中嵌套模板事物的完全专业化是不是实际上只是局部特化?有时候我很欣赏我大部分时间都使用VC++.好吧,有时我觉得我不想再使用C++了 (2认同)
  • 我投票给我做出这个决定的C++标准委员会.是时候用更好的语言打赌你的职业生涯了. (2认同)

Kir*_*sky 8

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

在类模板成员或出现在命名空间作用域中的成员模板的显式特化声明中,成员模板及其某些封闭类模板可能保持非专业化,除非声明不应明确专门化类成员模板封闭类模板也没有明确专门化.

  • "只有C++ Standard的创建者真的知道为什么会如此" - 是什么让你这么说?C++标准是通过一个开放的过程开发的,许多决策都在公开场合进行辩论:在邮件列表或新闻组,会议上.此外,Stroustrup写了一本关于C++背后的一些设计决策的书.你有没有检查过这个特定决定没有可用的信息,或者这是一个关于任何人可以"真正知道"什么的哲学论点?;-)语言设计不是一个黑盒子,"专家"走进去,标准出来了. (10认同)
  • 这不是我的问题的答案.如果您已经阅读了我的问题,您会注意到我已经知道不允许对嵌套类进行显式特化.我已经找到了绕过这一禁令的方法.我的问题是__为什么会这样?__ (8认同)
  • @Steve,"C++标准是通过一个开放的过程开发的"< - 这只是一些委员会成员想让人们相信的.不幸的是,它并不是真的开放.委员会邮件列表("反射器")显然大部分工作已经完成,但仍然是公众关闭的. (5认同)
  • @litb:是的,如果在早期安德鲁·柯尼希和Bjarne Stroustrup在电梯里相遇,没有人花上几分钟,那么谁知道可能做了什么黑暗交易.我的观点并不是说C++是完全透明的,只是基里尔的绝对陈述是非常吝啬的,考虑到在许多情况下,与C++相关的决策已经在公众场合播出令人作呕.我不知道这是否是其中之一,我只是觉得语言设计是程序员没有尝试思考或好奇的事情."重返工作岗位,劳动单位drhirsch";-) (4认同)
  • 只有C++ Standard的创建者真的知道为什么会这样. (2认同)

Mat*_* M. 7

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

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

template <class T>
struct Outer
{
  template <class U>
  struct Inner: detail::InnerImpl<T,U>
  {
  };
};
Run Code Online (Sandbox Code Playgroud)

现在你可以InnerImpl根据自己的意愿进行专业化

  • 是的:您可以注意到我将`T`传递给`InnerImpl`模板类. (2认同)