繁体   English   中英

了解继承的嵌套类模板的部分专业化

[英]Understanding partial specialization of inherited nested class templates

这个问题与先前的问答有关,在该问答中提到了gcc的错误报告(据说已在gcc 4.5.0中修复),并且涉及嵌套类模板的部分专业化的一些特殊性。

我的设置是我有一个带有嵌套类模板Inner Base类,该模板部分专门用于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

但是最奇怪的部分是,当我同时从BaseDerived调用Inner的各种局部专业化时,我仅对Derived所做的int的局部专业化也适用于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>是部分专用的?

使用gcc 4.8.0的在线示例 我正在特别寻找标准中解释这种行为的报价。

专业化模板不是多态性的一部分。

您实际上是在声明类型。 因此,任何可以看到派生的头文件以及模板专业化实现的编译单元都将对该嵌套模板类使用该专业化。

编译器将尝试查找最佳匹配类,并将始终选择默认类型以外的专用类型。 因此,即使您尝试访问基本类型的范围,它仍然是同一类。

如果您将模板类专门用于代码的任何其他部分,也会发生同样的事情。 编译器将选择最佳匹配的专业化,如果不匹配,将采用“默认”。

局部专业化必须重新声明与其提供替代定义的主模板相同的名称。

当您在Derived范围内编写struct Inner ,就是在声明Derived::Inner Base::Inner是与Derived::Inner不同的名称,因此声明了一个不同的类。 无法使用声明Derived::Inner的声明来专门化Base::Inner Derived::Inner

当您在命名空间范围内编写Derived::Inner时,名称查找会将名称解析为Base::Inner专业化都是同一类: Base::Inner ,即使您将它们称为Derived::Inner

从标准:

[temp.class.spec]

类模板的部分专业化提供模板的替代定义 ,当专门化中的参数与部分专业化中给出的参数匹配时,将使用模板的替代定义而不是主要定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM