用户定义的演绎指南是否涉及模板模板参数作为符合指导标准的模板

时间:2017-10-07 18:59:21

标签: c++ language-lawyer c++17 template-templates template-deduction

背景

昨天我问了一个关于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]/1simple-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 ++中实际允许,但认为当前的措辞确实使它符合要求。我错过了一些禁止代码的重要规则吗?

1 个答案:

答案 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 没有命名类模板专门化。

通过别名模板命名(Richard的例子)

理查德给出了另一个例子

template<typename T> class X { T t; };
template<typename T> using Y = X<T*>;
template<typename T> Y(T) -> Y<T>;

在这种情况下,它更复杂,我认为这可能是措辞允许的,因为Y<T>实际上是一个类模板专门化。在应用重写规则之后,您现在可以争论它是否实际名称专业化或仅表示它。它可以允许论证的事实似乎足以保证缺陷报告,IMO。