问题 Concepts-Lite如何与可变参数模板交互?


我看过Bjarne Strustrup的演讲 去本土2013 他为即将到来的C ++概念 - 精简功能提供了以下示例。

void sort(Container& c); // terse notation

// Expands to
template <Container __Cont>
  void sort(__Cont& c); // shorthand notation

// Expands to 
template <typename __Cont>
  requires Container<__Cont>()
    void sort(__Cont & c);

我的问题是如何使用可变参数模板?

我想要定义一个可变参数 maximum 使用a的功能 Comparable 概念。是否接受以下语法?

auto maximum(Comparable a)
{
     return a;
}

auto maximum(Comparable c, Comparable... rest)
{        
    return std::max(a, maximum(rest...));
}

如果是这样的话 Comparable... 意味着参数包中的所有元素都是相同类型或只是它们都是 Comparable 类型,以便包可以包括两者 int 和 string? (两者相当,但彼此不相同)

好奇的人想知道。


12644
2017-09-15 11:19


起源



答案:


我认为简洁格式的目的是要求包中的所有元素必须是相同的类型。这是从n3701§5.3中的例子中得出的,该例子说明了这一点

void sort(Random_access_iterator p, Random_access_iterator q);

应该相当于

template<Random_access_iterator __Ran>
void sort(__Ran p, __Ran q);

因为

“默认情况下,如果使用相同的约束参数   两个参数的类型名称,这些参数的类型必须相同。   我们选择重复使用约束参数类型名称暗示   “相同类型”,因为(在大多数环境中)是最常见的情况,   在一个范围内使用两次的标识符有两个不同是很奇怪的   意思是,这里的目的是优化最简单案例的简洁记法。“

但我不知道它如何扩展到你的 maximum 使用当前('14)模板语法。在n3701中提出的标准措辞的改变中,它只谈到了简单的案例

§7.1.6.5约束类型说明符[dcl.spec.constrained]

...

第一次使用 概念名 要么 局部概念-ID 在一个范围内绑定   命名为占位符类型,以便后续使用相同名称引用   相同的类型。

但它并没有解释可变参数的相互作用。也许需要等待第3次修订才能澄清这一点。


7
2017-09-15 11:40



在OPs示例中,它不仅是参数包,还是第一个参数。您的回答也向Concepts的作者提出了如何编写函数的问题 void sort( Iterator a, Iterator b ); 当我明确想要的时候 a 和 b 被允许有不同的类型。嗯。我不得不承认我从来不是概念的粉丝...: - / - Daniel Frey
@DanielFrey:如果你需要的话 a 和 b 不同,不要使用简洁的形式。 template <Iterator A, Iterator B> void sort(A a, B b);。 - kennytm
对,傻我。 - Daniel Frey
@DanielFrey:我也想不出怎么写 auto maximum(Comparable c, Comparable... rest) 成 template <????> auto (???? c, ????... rest); 同时要求全部 c 和 rest... 具有相同的类型,因此答案中的最后一句话。 - kennytm
@KennyTM require 包充满了相同的类型,如果非空,则该类型的实例符合要求。概念并不难,但比非变量情况更复杂的转换。 - Yakk - Adam Nevraumont


答案:


我认为简洁格式的目的是要求包中的所有元素必须是相同的类型。这是从n3701§5.3中的例子中得出的,该例子说明了这一点

void sort(Random_access_iterator p, Random_access_iterator q);

应该相当于

template<Random_access_iterator __Ran>
void sort(__Ran p, __Ran q);

因为

“默认情况下,如果使用相同的约束参数   两个参数的类型名称,这些参数的类型必须相同。   我们选择重复使用约束参数类型名称暗示   “相同类型”,因为(在大多数环境中)是最常见的情况,   在一个范围内使用两次的标识符有两个不同是很奇怪的   意思是,这里的目的是优化最简单案例的简洁记法。“

但我不知道它如何扩展到你的 maximum 使用当前('14)模板语法。在n3701中提出的标准措辞的改变中,它只谈到了简单的案例

§7.1.6.5约束类型说明符[dcl.spec.constrained]

...

第一次使用 概念名 要么 局部概念-ID 在一个范围内绑定   命名为占位符类型,以便后续使用相同名称引用   相同的类型。

但它并没有解释可变参数的相互作用。也许需要等待第3次修订才能澄清这一点。


7
2017-09-15 11:40



在OPs示例中,它不仅是参数包,还是第一个参数。您的回答也向Concepts的作者提出了如何编写函数的问题 void sort( Iterator a, Iterator b ); 当我明确想要的时候 a 和 b 被允许有不同的类型。嗯。我不得不承认我从来不是概念的粉丝...: - / - Daniel Frey
@DanielFrey:如果你需要的话 a 和 b 不同,不要使用简洁的形式。 template <Iterator A, Iterator B> void sort(A a, B b);。 - kennytm
对,傻我。 - Daniel Frey
@DanielFrey:我也想不出怎么写 auto maximum(Comparable c, Comparable... rest) 成 template <????> auto (???? c, ????... rest); 同时要求全部 c 和 rest... 具有相同的类型,因此答案中的最后一句话。 - kennytm
@KennyTM require 包充满了相同的类型,如果非空,则该类型的实例符合要求。概念并不难,但比非变量情况更复杂的转换。 - Yakk - Adam Nevraumont


我不知道是否 N3580 是概念文件的最新版本,但在4.5.1中似乎描述了类型需求如何与可变参数列表一起使用。看起来

template <Comparable... T>
auto maximum(T... values) -> <return-type-goes-here>

将要求每个参数满足 Comparable 要求但类型没有限制 T... 都是一样的。这项要求需要单独强制执行。另一方面,我知道如何强加相同类型要求的唯一方法是与C ++ 11中相同的方法,但概念设施可能有更好的方法。


6
2017-09-15 12:28



C ++ 14是否允许隐式返回类型 auto 所以不需要<return-type-goes-here>? - Motti
@Motti:如果我没记错的话,这取决于你的函数是如何写的。鉴于类型都不同,我不太确定编译器是否可以解决它。 - Dietmar Kühl
是的,我的问题的重点是要问 是否 类型不同。 - Motti
@Motti:......我想我已经回答了这个问题:“......但是这些类型并没有限制 T... 都是一样的“ - Dietmar Kühl
N3701是更高版本:(013-06-28) open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3701.pdf - Johan Lundberg