昨天我问了一个关于guarantees of deduction guides usage in case of template template parameters的问题。当Barry改变了对代码标准符合性确认的答案时,我感到非常惊讶。我的意外实际上并不是因为扣除指南可以应用于模板模板参数,而是来自符合此合规性的标准部分,即[temp.param]/3:
type-parameter ,其标识符不遵循省略号,将其标识符定义为 typedef-name (如果声明没有
template
)或 template-name (如果用template
声明)在模板声明的范围内。
此加号[temp.deduct.guide]/1和simple-template-id规则允许用户创建接受任何模板的通用演绎指南。
#include <string>
template <class T>
struct Foo {
Foo(T) { }
};
template <template <class> class TT>
TT(const char *) -> TT<std::string>;
int main() {
Foo foo("abc");
}
代码导致gcc因内部错误而崩溃,并导致clang中的编译错误。说实话,我不说代码应该在C ++中实际允许,但认为当前的措辞确实使它符合要求。我错过了一些禁止代码的重要规则吗?
答案 0 :(得分:1)
冒错误的风险,我会引用一个现已删除的答案
如果我没有弄错,这与[temp.deduct.guide] p3相反:
simple-template-id应命名一个类模板特化。
TT<std::string>
没有命名类模板特化,而且您的代码格式不正确。[temp.spec] p4中也有这个:
特化是一个实例化或显式专用的类,函数或类成员。
TT
在技术上是 type-parameter 模板。构造TT<std::string>
是类型相关的类型名称。如果演绎指南是实际的函数模板并且我们将实例化它,TT<std::string>
可以被实例化为引用类模板特化的 class-name 。如果int
被实例化以引用适当定义的别名模板,它也可以引用TT
。但是,在演绎指南声明中,它还没有命名一个类模板专门化。
[temp.res] p8.5.5中有一条规则说
否则,不能为可以生成有效特化的模板发出诊断。
那么,演绎指南的专业化是否可以发生?我和没有争论。首先,它不是一个可以实例化的“模板化实体”(c.f. [temp] p8)。专门用于类模板参数推导的是一组模板,这些模板是基于演绎指南形成的,而不是自己的指南。见[over.match.class.deduct] p1.4
[...]对于每个演绎指南,形成具有以下属性的函数或函数模板[形成]:[...]
这些功能模板在过载分辨过程中进一步专门化。扣除指南本身从不专门化,因此,我们可以生成诊断消息,违反规则,即演绎指南中的 simple-template-id 没有命名类模板专门化。
理查德给出了另一个例子
template<typename T> class X { T t; };
template<typename T> using Y = X<T*>;
template<typename T> Y(T) -> Y<T>;
在这种情况下,它更复杂,我认为这可能是措辞允许的,因为Y<T>
实际上是一个类模板专门化。在应用重写规则之后,您现在可以争论它是否实际名称专业化或仅表示它。它可以允许论证的事实似乎足以保证缺陷报告,IMO。