这个问题与a previous Q&A有关,其中提到了gcc的错误报告(据说已在gcc 4.5.0中修复),并涉及嵌套类模板的部分特化的一些特殊性。

我的设置是,我有一个带有嵌套类模板BaseInner类,该类模板专门用于char(使用虚拟参数技巧,因为在类中不允许显式指定)。

#include <type_traits>
#include <iostream>
#include <ios>

struct Base
{
    // dummy template parameter...
    template<class U, class _ = void> struct Inner: std::true_type {};

    // ... to allow in-class partial specialization
    template<class _> struct Inner<char, _>: std::false_type {};
};

现在,我定义了一个Derived类,我想进一步对其进行特化处理Inner,由于某种奇怪的原因,它不能在类里面完成(即使它仍然是部分特化处理)。
struct Derived
:
    Base
{
    // cannot partially specialize Inner inside Derived...
    //template<class _>
    //struct Inner<int, _>: std::false_type {};
};

// ... but specializing Derived::Inner at namespace scope, also specializes it for Base::Inner
template<class _> struct Derived::Inner<int, _>: std::false_type {};

第一个问题:为什么我必须在命名空间范围内部分专门化Derived::Inner

但是最奇怪的部分是,当我从InnerBase调用Derived的各个部分特化时,我只对int进行的Derived的部分特化也适用于Base
int main()
{
    std::cout << std::boolalpha << Base::Inner<float>::value << "\n";
    std::cout << std::boolalpha << Derived::Inner<float>::value << "\n";

    std::cout << std::boolalpha << Base::Inner<char>::value << "\n";
    std::cout << std::boolalpha << Derived::Inner<char>::value << "\n";

    std::cout << std::boolalpha << Base::Inner<int>::value << "\n";      // huh???
    std::cout << std::boolalpha << Derived::Inner<int>::value << "\n";   // OK
}

第二个问题:为什么Base::Inner<int>::value等于false,即使仅Derived::Inner<int>是部分专用的?

Online example using gcc 4.8.0。我正在特别寻找标准中解释这种行为的报价。

最佳答案

局部特化必须重新声明与其提供替代定义的主要模板相同的名称。
当您在struct Inner范围内编写Derived时,就是在声明Derived::InnerBase::Inner是与Derived::Inner不同的名称,因此声明了一个不同的类。不能使用声明Base::Inner的声明来专门化Derived::Inner
在命名空间范围内编写Derived::Inner时,名称查找会将其名称解析为Base::Inner-特化都是同一类:Base::Inner,即使您将它们称为Derived::Inner也是如此。
从标准:

关于c++ - 了解继承的嵌套类模板的部分特化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17132753/

10-14 07:10