c++ - 关于类模板成员的显式特化的困惑

标签 c++ templates language-lawyer

template<class T> struct A {
  struct B { };
  template<class U> struct C { 
      void show();
  };
};

template<>
template<>
void A<int>::C<int>::show(){  //#1

}

int main(){

}
考虑上面的code,在#1处,它是成员类模板成员的显式专门化定义。某些规则将按照以下规定应用于它:
temp.expl.spec#5

A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined. The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of a generated specialization. Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax. The same is true when defining a member of an explicitly specialized member class. However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.


首先,explicitly specialized class是什么?它是否指代具有明确专门化声明的实体?似乎并不意味着它,请看Explicitly specialized class部分中的示例
template<> template<> class A<int>::B<double>;
根据该示例,可以将成员的显式专门化内的A<int>称为explicitly specialized class。因此,在我的第一个示例中,A<int>C<int>都是explicitly specialized class吗?我不确定。我觉得这部分词explicitly specialized class不清楚。
请注意强调的部分,这意味着封闭类模板的显式特化应在与其成员的显式特化定义相同的范围内出现。该成员是在全局范围内定义的,但是在全局范围内没有针对A<int>C<int>的任何明确的专门化定义。如何解释呢?
顺便说一下,作为一个相反的例子:
template<class T> struct A {
  struct B { };
  template<class U> struct C { 
      void show();
  };
};

template<>
template<typename U>
struct A<int>::C{  //#2
    void show();
};

template<>
template<typename U>
void A<int>::C<U>::show(){  //#3

}

int main(){

}
为什么在C之前需要此类代码对类模板#3进行显式专门化,所以这两个示例之间有什么区别?
专门课
在本节中,“显式专业类”一词不清楚,
temp.expl.spec#15

A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized.

[ Example:  
template<class T1> class A {
  template<class T2> class B {
    void mf();
  };
};
template<> template<> class A<int>::B<double>;
template<> template<> void A<char>::B<char>::mf();
— end example ]  
explicitly specialized class是什么意思,它是指具有显式专门化声明或其他内容的实体吗?在上面的示例中,似乎对A<int>没有明确的特化。

最佳答案

那里没有混乱,您必须根据它们的语法结构来解析这些语句(C++和英语)。源代码是以人类可以理解的语言描述的程序。编程语言是人类合作的工具。
CWG529通过更改措辞来解释模板ID的顺序和内容,从而消除了直观理解的需求。
在这里,您使用模板参数T声明了类A的模板,模板参数T包含类B,并使用模板参数U声明了模板类C的嵌套声明,其中包含了方法show():

template<class T> struct A {
  struct B { };
  template<class U> struct C { 
      void show();
  };
};
在这里,您声明了带有T = int的显式专门化的模板类A(需要首先声明它),存在一个模板类C,其中包含方法show()
template<>
template<typename U>
struct A<int>::C{  //#2
    void show();
};
该声明与先前的声明并不矛盾,但是由于它是A类的专门化,因此可以对其进行扩展!你可以这样做:
template<>
template<typename U>
struct A<int>::C{  //#4
    void hide();
};
这意味着,对于任何带有T=int的A,都有一个模板类C获得成员hide()。但是其他A的模板类C的成员为show()。先前的声明所做的事情消除了对该A的特化对C的内容的任何疑问。
现在,这只为show()中包含的所有C定义了成员函数A<int>:
template<>
template<typename U>
void A<int>::C<U>::show(){  //#3

}
您在这里没有C的显式特化,这是show()的封闭类。成员ID show()之前是未特化的模板ID template<typename U> ... C<U>。只有成员函数的定义,但它需要该模板C的可见声明-#2部分。可见性可以通过各种方式获得,并且所提及的“范围”是对其的概括描述。
省略第2部分将相当于写作的语义:
class C;

void C::show() { // ill-formed - C is an incomplete type.
}
我们知道所有的A都包含一些C类,但是我们在专门的A<int>中没有针对该特定C的完整定义(可能有所不同)。
该语句实际上表明嵌套在特化C<int>中的特化A<int>包含show()
template<>
template<>
void A<int>::C<int>::show(){  //#1

}
矛盾,歧义或不确定性的任何可能性(除了不确定的行为之外)都导致代码格式错误,而规则则旨在形成应检查代码的限制框架。在没有#2的情况下,在某个位置#3后面可以接#4,然后#3语句将变为非法,因此被认为是非法的。 #2和#4同时是同一事物的两个定义,如果它们出现在同一单元中,也可能导致格式错误的代码,或者如果它们出现在程序中的不同单元中,则它们将导致 undefined 的行为。

关于c++ - 关于类模板成员的显式特化的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63131417/

相关文章:

c++ - 转换为眼空间的问题

c++ - 比较模板类中的枚举 - 它安全吗?

c++ - 通过 const 指针修改用 new 创建的对象是否合法?

rust - 对于所有类型 `T` 、 `U` 是否真的,如果 `T` 被强制转换为 `U` 那么 `&T` 被强制转换为 `&U` ?

c++ - 编译器如何知道其他 .cpp 文件如何使用静态常量成员?

c++ - 在 vector 上使用迭代器时,'std::bad_alloc' 甚至是错误的 vector 大小

c++ - 奇怪的这个->行为

c++ - 将成员函数从基类移动到派生类会无缘无故地破坏程序

c++ - 这个 C++ 模板成员函数声明是如何工作的?

c++ - C++ 语法演化是如何管理的?