问题 类模板显式特化还可以声明其他东西吗?


如果这段代码无效,那就太好了。但它在概念上是合理的,而且是海湾合作委员会 接受它 尽管Comeau没有:

template< typename > struct t;

template<> struct t< int > {} r; // Bad declarator! Don't pee on the carpet!

编辑: 以上编译但是 r 似乎没有被宣布 进入任何范围,所以它基本上被忽略了。)

显式特化在模板和类之间填充一种下层区域。一旦定义,显式特化声明的类型就完成了。从编译器的角度来看,它不是模板。如果它是参数化模板,则无法声明对象。考虑§14/ 3:

在模板声明,显式特化或显式实例化中,声明中的init-declarator-list最多应包含一个声明符。当这样的声明用于声明类模板时,不允许声明者。

“用于声明类模板”是什么意思?显然,主模板声明了一个类模板。根据§14.5.5/ 1(FDIS编号),部分专业化也是如此:

类模板名称是simple-template-id的模板声明是simple-template-id中指定的类模板的部分特化。

然而,当谈到显式专业化时,标准就是在令牌序列之前的声明方面说话 template<>。它 容貌 像模板一样,它命名一个模板名称,但它似乎没有声明模板。

真正奇怪的是§14/ 3将声明者的数量限制为“最多一个”。函数模板声明,显式特化或实例化必须只有一个声明符。涉及类模板的任何声明必须具有正确的零...除了显式特化,这似乎是通过裂缝。忠实于海湾合作委员会 拒绝允许 

template<> struct t< int > {} r, s; // Offer valid one per specialization.

我倾向于同意海湾合作委员会的解释,尽管可能是胡说八道。不幸的是,它可能是 抑制 它能够检测缺失的分号。请允许声明者的数量正好为零!


9789
now


起源

考虑 template<typename T> template<typename U> struct A { struct B { }; }; template<> template<typename T> struct A<int>::A { };。这里,对实例化的成员模板进行显式特化 A<int>,但没有专门化成员模板本身(这种显式专业化没有真正的术语。在某一点上,规范在引用这种情况时使用术语“专门作为模板”:“但是,模板< >用于定义专门用作类模板的显式专用成员类模板的成员。“)。 - Johannes Schaub - litb
出于好奇,我尝试用clang ++编译它。它在变量'r'的声明中输出错误“无关'模板<>'。显然,当tempalte <>被省略时,它会出现错误“模板专业化需要'模板<>'”。 - CygnusX1


答案:


有几点:首先,明确的专业化并不是一件好事 模板和类之间的区域;明确的专业化是一个 上课,期间。唯一的关系是模板(除了 有趣的名称)是它将被用来代替模板实例化 如果要在特化类型上实例化模板。

其次,如果§14/ 3中的段落存在问题 引用,它包括明确的实例化;明确的 instantiation是一个类定义,如果

struct S {} s, *p;

是合法的,

template<> struct T<int> {} s, *p;

应该也是。 (我会反对允许,但那列车 已经离开了车站,而且由于C允许第一次,我们被卡住了 用它。)

否则,§14/ 3中的陈述有点无关紧要。一个功能 模板必须只有一个声明符和一个类模板 零;没有必要试图让他们两个人“至多一个” 官样文章。 (如果我从头开始设计语言,我不会 允许在声明中定义类或枚举的任何声明符 类型。但同样,这已经太迟了。)

我同意这是一个麻烦:

template<> struct T<int> {};    //  Requires a ';'
template<> void f<int>() {}     //  ';' forbidden

(在函数定义之后,至少C ++ 11将允许使用分号。)


13
2018-06-10 09:43



为中等夸张的散文道歉。这个答案与我的理解和意见相吻合(尽管希望以特定的方式修复GCC错误),但参考会很好。毕竟,Comeau确实拒绝了我的第一个例子。 - Potatoswatter
@Potatoswatter不需要道歉。我能理解你的观点。关于我的理解:我一直都知道类模板的实例化(无论是否显式)是一个类,而函数模板的实例化是一个函数。但是现在我在标准中寻找它,我找不到这种效果的陈述;也许是第一句话:“模板定义了一个类或函数族”(所以每个实例都是一个家族的成员,即一个类或一个函数)? - James Kanze
我认为在语义上,它指定显式实例化根据需要生成类或函数(显式实例化甚至可以再次生成模板。示例: template<typename T> struct A { template<typename B> void f() { } }; template struct A<int>;,实例化成员模板 A<T>::f 产生另一个成员模板 A<int>::f)。 FDIS在14.7p4说:“专业化是一个类,功能或类成员,要么实例化要么明确专门化(14.7.3)。” - Johannes Schaub - litb
但我无法找到它所说的显式实例化是它创建的实体的声明。也就是说,我无法找到它所说的上述内容 template struct A<int>; 是类声明或类定