【问题标题】:Are user defined deduction guides involving template template parameter as a template for guidance standard compliant用户定义的涉及模板模板参数的扣除指南是否符合指导标准的模板
【发布时间】:2018-03-19 08:07:13
【问题描述】:

背景

昨天我问了一个关于guarantees of deduction guides usage in case of template template parameters的问题。当 Barry 改变他对确认代码标准合规性的回答时,我真的很惊讶。令我惊讶的其实并不是模板模板参数可以应用推演指南,而是更多来自符合这种合规性的标准部分,即[temp.param]/3

一个type-parameter,其标识符不跟在省略号后面,将其标识符定义为一个typedef-name(如果声明时没有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++ 中被允许,但认为当前的措辞确实使其符合。我是否遗漏了一些不允许代码的重要规则?

【问题讨论】:

  • 天哪。我希望这是不允许的:)
  • @Barry 是的,这会很烦人 :) 可以明确禁止以尽量减少对标准其他部分的影响...
  • 来自 Richard Smith,大声笑:“哈,我们从未想过这是有效的,但我看不出当前措辞中有任何禁止它的规则。”这最终会成为核心语言缺陷。
  • @Barry 在下面看到我的回答

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


【解决方案1】:

你的例子

冒着出错的风险,我会引用一个现已删除的答案

如果我没记错的话,这与 [temp.deduct.guide]p3 冲突:

simple-template-id 应命名一个类模板特化。

TT&lt;std::string&gt; 没有命名类模板特化,并且您的代码格式不正确。

[temp.spec]p4 中也有这个:

特化是被实例化或显式特化的类、函数或类成员。

TT 在技术上是一个模板类型参数。而构造TT&lt;std::string&gt; 是一个依赖于类型的type-name。如果 deduction-guide 是一个实际的函数模板并且我们将实例化它,TT&lt;std::string&gt; 可以实例化为引用类模板特化的 class-name。如果 TT 被实例化以引用适当定义的别名模板,它也可以引用 int。但照原样,在演绎指南声明中,它还没有命名类模板特化。

[temp.res]p8.5.5 中有一条规则说

否则,不会为可以生成有效专业化的模板发出诊断。

那么,演绎指南的专业化能否实现?我反对no。首先,它不是可以实例化的“模板化实体”(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&lt;T&gt; 实际上是一个类模板特化。在应用了重写规则之后,您现在可以争论它是真正命名专业化还是仅仅表示它。它可以允许争论的事实似乎足以保证缺陷报告,IMO。

【讨论】:

  • 我不知道你是怎么做到的,但你总是让我大吃一惊;)让我再分析一下你的答案,以确定我是否真的理解它:)
  • @W.F.我的论点是它没有命名类模板专业化。它的依赖是值得注意的。但这本身并不是原因。在Foo&lt;T&gt; 中,名称Foo&lt;T&gt; 命名了类模板Foo 的一个(未知)特化,因此它命名了一个类模板特化。但是在TT&lt;std::string&gt; 中,它命名了一个未知类型(因此我注意到它是一个依赖类型)。因此,在演绎指南定义时,该名称并未命名类模板特化。
  • 是的 - 对不起,我再次阅读了您的(正如我所说的令人兴奋的)答案,我想我明白了您关于依赖 type-name 的观点......我以前没有见过它,因为TT (AFAIK) 如果它是别名,则无法真正推断出来......我认为这可能是答案,也许这里毕竟没有语言缺陷......
猜你喜欢
  • 1970-01-01
  • 2020-11-30
  • 2020-02-17
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多