简体   繁体   English

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

[英]Understanding partial specialization of inherited nested class templates

This question is connected to a previous Q&A in which a bug report for gcc was mentioned (supposedly fixed in gcc 4.5.0) and concerns some peculiarities for partial specialization of nested class template. 这个问题与先前的问答有关,在该问答中提到了gcc的错误报告(据说已在gcc 4.5.0中修复),并且涉及嵌套类模板的部分专业化的一些特殊性。

My setup is that I have a class Base with a nested class template Inner that is partially specialized for char (using the dummy parameter trick, because explicit speciliaztion is not allowed in-class). 我的设置是我有一个带有嵌套类模板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 {};
};

I now define a Derived class for which I further want to specialize Inner , which for some odd reason cannot be done in-class (even though it is still a partial specialization). 我现在定义一个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 {};

First question : why do I have to partially specialize Derived::Inner at namespace scope? 第一个问题 :为什么我必须在命名空间范围内部分专门化Derived::Inner

But the strangest part is that when I call the various partial specializations of Inner from both Base and Derived , the partial specialization for int that I only did for Derived , also applies to Base . 但是最奇怪的部分是,当我同时从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 
}

Second question : why is Base::Inner<int>::value equal to false , even though only Derived::Inner<int> was partially specialized? 第二个问题 :为什么Base::Inner<int>::value等于false ,即使仅Derived::Inner<int>是部分专用的?

Online example using gcc 4.8.0 . 使用gcc 4.8.0的在线示例 I am specifically looking for quotes from the Standard that explain this behavior. 我正在特别寻找标准中解释这种行为的报价。

Specializing templates isn't a part of polymorhpism. 专业化模板不是多态性的一部分。

You're in fact declaring a type. 您实际上是在声明类型。 So any compilation unit that can see the derived header file with the implementation for the template specialization will use that specialization for the nested template class. 因此,任何可以看到派生的头文件以及模板专业化实现的编译单元都将对该嵌套模板类使用该专业化。

The compiler tries to find the best match class, and will always choose the specialized type over the default. 编译器将尝试查找最佳匹配类,并将始终选择默认类型以外的专用类型。 So even if you try to access the scope of the base type it's still the same class. 因此,即使您尝试访问基本类型的范围,它仍然是同一类。

Same thing would happen if you specialize a template class in any other part of your code. 如果您将模板类专门用于代码的任何其他部分,也会发生同样的事情。 The compiler will choose the best matching specialization, if there is non, it will take the "default". 编译器将选择最佳匹配的专业化,如果不匹配,将采用“默认”。

A partial specialization must redeclare the same name as the primary template for which it provides an alternative definition. 局部专业化必须重新声明与其提供替代定义的主模板相同的名称。

When you write struct Inner within the scope of Derived , you are declaring Derived::Inner . 当您在Derived范围内编写struct Inner ,就是在声明Derived::Inner Base::Inner is a distinct name from Derived::Inner and therefore declares a different class. Base::Inner是与Derived::Inner不同的名称,因此声明了一个不同的类。 It is not possible to specialize Base::Inner with a declaration that declares Derived::Inner . 无法使用声明Derived::Inner的声明来专门化Base::Inner Derived::Inner

When you write Derived::Inner at namespace scope, name lookup resolves that name to Base::Inner - the specializations are all of the same class: Base::Inner , even if you refer to them as Derived::Inner . 当您在命名空间范围内编写Derived::Inner时,名称查找会将名称解析为Base::Inner专业化都是同一类: Base::Inner ,即使您将它们称为Derived::Inner

From the standard: 从标准:

[temp.class.spec] [temp.class.spec]

A partial specialization of a class template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization. 类模板的部分专业化提供模板的替代定义 ,当专门化中的参数与部分专业化中给出的参数匹配时,将使用模板的替代定义而不是主要定义。

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

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