背景
昨天我问了一个关于guarantees of deduction guides usage in case of template template parameters的问题 . 当Barry改变了对代码标准符合性确认的答案时,我感到非常惊讶 . 令我惊讶的是,实际上并不是因为扣除指南可以应用于模板模板参数,而是来自符合此合规性的标准部分,即[temp.param]/3:
标识符不遵循省略号的类型参数将其标识符定义为模板声明范围内的typedef-name(如果声明没有模板)或template-name(如果使用模板声明) .
加上[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中的编译错误 . 说实话,我是 not 说代码应该在C中实际允许但是认为当前的措辞确实使它符合要求 . 我错过了一些不允许代码的重要规则吗?
1 回答
你的例子
冒错误的风险,我会引用一个现已删除的答案
TT
技术上是模板类型参数 . 构造TT<std::string>
是类型相关的类型名称 . 如果演绎指南是一个实际的函数模板,我们将实例化它,TT<std::string>
可以实例化为引用类模板特化的类名 . 如果TT
被实例化以引用适当定义的别名模板,它也可以引用int
. 但是,在演绎指南声明中,它还没有命名一个类模板专门化 .在[temp.res] p8.5.5中有一条规则说
那么,演绎指南的专业化是否会发生呢?我争辩说不 . 首先,它不是可以实例化的"templated entity"(c.f . [temp] p8) . 专门用于类模板参数推导的是一组模板,这些模板是基于演绎指南而形成的,而不是自己的指南 . 见[over.match.class.deduct] p1.4
这些功能模板在过载分辨过程中进一步专门化 . 演绎指南本身从不专门化,因此,我们可以生成违反规则的诊断消息,即演绎指南中的simple-template-id没有命名类模板特化 .
用别名模板命名(Richard的例子)
理查德举了另一个例子
在这种情况下,它更复杂,我认为这可能是由措辞允许的,因为
Y<T>
实际上是一个类模板专门化 . 在重写规则应用之后,您现在可以争论它是否实际命名专业化或仅表示它 . 它可能允许争论的事实似乎足以保证缺陷报告,IMO .