【问题标题】:C++ Concepts with multiple template arguments具有多个模板参数的 C++ 概念
【发布时间】:2017-02-23 10:41:32
【问题描述】:

Bjarne Stroustrup 最近在 C++ 概念上发表了 report,他提到了一些令我惊讶的事情。该示例(在第 7.1 节中)使用“速记模板表示法”,基本上是这样的:

void foo1(auto x,auto y);                // x and y may have different types  (1)
void foo2(SomeConcept x,SomeConcept y);  // x and y must have the same type   (2)

就我个人而言,这似乎非常违反直觉;事实上,只要各自的类型满足 SomeConcept,我希望 foo2 接受不同类型的值 x,y。请注意,程序员始终可以通过编写以下内容之一来明确指定其意图:

template <SomeConcept T> void foo2(T x, T y);                   // (3)
template <SomeConcept T1,SomeConcept T2> void foo2(T1 x,T2 y);  // (4)

直观地说,我希望 (2) 中的简写符号等同于 (4),因此更符合无约束模板 (1) 的含义。有人可以阐明这个问题并解释这个设计决定背后的基本原理吗?

一些备注:

  • afaik,通用 lambda(在 C++14 中)已经允许使用类似于 (1) 的语法。因此,一致性要求 (1) 应该接受不同类型的输入变量,因为通用 lambda 可以做到这一点。
  • Stroustrup 在此类模板的上下文中提到了经典的“迭代器对”。但是,我认为这是一个相当薄弱的论点,因为 (i) 这只是一个用例,并且 (ii) afaik,C++17 引入了 (iterator, sentinel) 对,这强制通用代码无论如何都要使用两种不同的类型.

【问题讨论】:

  • 同意这是违反直觉的。我真的很想要缩写语法,只要它允许相同概念的不同类型。
  • 请注意,论文主要代表作者的观点,不一定代表委员会的观点。而且我认为委员会对概念的看法远非一致(从过去的邮件中可以看出)。最终会发生什么还有待观察;您要查找的是已通过的委员会动议。
  • Concepts TS 的当前版本(第 8.3.5 节,第 22 页)中规定了相同的规则:open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4641.pdf

标签: c++ templates c++-concepts


【解决方案1】:

我能找到的在当前概念提案的上下文中提到简洁语法的最早论文是N3580,它在第 6.2.2 节中提供了这个理由:

如果我们需要相同概念的两种参数类型怎么办?考虑

void sort(Ran p, Ran q);

为此,pq 必须属于同一类型,这就是规则。默认情况下,如果您对两个参数使用相同的约束参数名称,则这些参数的类型必须相同。我们选择重复使用受约束的参数名称暗示“相同类型”,因为(在大多数环境中)这是最常见的情况,这里的目的是优化 最简单情况的简洁表示法。此外,受约束的参数是名称 属于一个类型,并且有两个类型名称是指同一范围内的不同类型 会造成混乱。

Tony van Eerd 和 Boton Ballo 提出了更改此含义的建议:P0464。该论文提供了两个论据来支持当前的含义,一个类似于 Sutton 等人提出的论据,另一个是正交的:

使用频率
可以说,您通常不希望一个函数接受两个可能不同类型的参数,满足相同的概念,而这两种类型之间没有额外的关系。

与定义检查的交互
还可以说,这种变化将鼓励模板作者编写约束不足的模板,因为即使在参数类型应该有额外约束的情况下,他们也会选择使用简洁的R foo(ConceptName, ConceptName); 形式。约束不足模板的激增将使定义检查的引入更加困难,因为约束不足的模板将无法通过定义检查。


我不熟悉任何其他支持当前语法的论点,但如果您熟悉,请随时通过电子邮件发送 Tony 和 Botond 以将其纳入他们的论文。

【讨论】:

  • 感谢您的回复。在我最初的问题之后,我实际上找到了 Botond 的提案,我希望它得到委员会的支持。就我个人而言,主要论点是与“自动”语法的一致性,但 Botond 似乎已经在他的提案中说明了这一点。
【解决方案2】:

只是为那些标记此问题或在 Google 上找到它的人提供的快速更新。

在 2018 年 3 月杰克逊维尔的 C++ 标准会议之前,这里讨论的问题已经解决了——显然是悄无声息的。引用Botond's trip report

顺便说一句,似乎没有太多讨论就解决了的一个话题是独立决议一致决议的问题;也就是说,如果您在 AFT 中有两次使用相同的概念(如在 void foo(Number, Number); 中),它们是否需要是相同的具体类型(“一致的”),或者两种可能不同的类型都对概念进行建模(“独立的”)。 Concepts TS 具有一致的分辨率,但许多人更喜欢独立分辨率。不久前,我与人合着了一篇主张独立解决的论文;随后另一篇论文以及Sortable{S} 提案的一部分也强化了这种情绪。让我觉得有点好笑的是,这个话题实际上从未被正式讨论过和投票过。独立决议的想法似乎慢慢地,随着时间的推移,赢得了人们的支持,以至于在这次会议上,它被视为已经达成的协议,任何进入 C++20 的 AFT 提案实际上都将具有独立的分辨率。

【讨论】:

  • 并且应该注意的是,圣地亚哥会议上实际批准的版本遵循了这一点:每个参数都独立于所有其他参数。应该是这样。
  • 发生的事情是 void f(Concept x); 语法是 removed entirely(影响最终的 wording paper),然后是 reintroducedauto 和(实际上是默认的)“独立解析”。
  • @NicolBolas 那么当您尝试将两个参数转发到另一个函数并且必须显式声明类型时会发生什么,现在有两种不同类型的同名?它“正常工作”吗?
  • @Gukki5: ...我不明白你在说什么。为什么必须显式声明类型?如果目标模板要求两种类型相同,那么为什么不声明函数参数以使它们产生相同的类型?记住:缩写的模板语法并不打算用于everything;你总是可以把它写成长格式。
猜你喜欢
  • 1970-01-01
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
相关资源
最近更新 更多