为什么没有将产量添加到C++ 0x?

tts*_*ras 30 c++ yield c++11 c++17

我在许多Python程序中都使用了yield,在很多情况下它确实清除了代码.我在博客上写了这篇文章,这是我网站的热门网页之一.

C#还提供了收益 - 它通过调用者端的状态保持来实现,通过自动生成的类来完成,该类保持状态,函数的局部变量等.

我目前正在阅读有关C++ 0x及其添加的内容; 在阅读有关C++ 0x中lambda的实现时,我发现它也是通过自动生成的类完成的,配备了存储lambda代码的operator().我心中形成了一个自然的问题:他们是为lambdas做过的,他们为什么不考虑支持"收益"呢?

当然,他们可以看到合作例程的价值......所以我只能猜测他们认为基于宏的实现(例如Simon Tatham的)是一个充分的替代品.然而,它们不是出于多种原因:被调用者保持状态,非重入状态,基于宏观(仅此一点是足够的理由)等.

编辑: yield不依赖于垃圾收集,线程或光纤.您可以阅读Simon的文章,看看我在谈论编译器进行简单的转换,例如:

int fibonacci() {
    int a = 0, b = 1;
    while (true) {
        yield a;
        int c = a + b;
        a = b;
        b = c;
    }
}
Run Code Online (Sandbox Code Playgroud)

成:

struct GeneratedFibonacci {
    int state;
    int a, b;

    GeneratedFibonacci() : state (0), a (0), b (1) {}

    int operator()() {
        switch (state) {
        case 0:
            state = 1;
            while (true) {
                return a;

        case 1:
                int c = a + b;
                a = b;
                b = c;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

垃圾收集?号码线程?不是纤维?不.简单转型?可以说是的.

jal*_*alf 22

我不能说为什么他们不添加这样的东西,但在lambdas的情况下,他们不仅仅是添加到语言中.

他们在Boost中开始了作为库实现的生活,证明了这一点

  • lambdas是非常有用的:很多人会在它们可用时使用它们
  • C++ 03中的库实现存在许多缺点.

基于此,委员会决定在C++ 0x中采用某种 lambdas,我相信他们最初尝试添加更多通用语言功能,以允许比Boost 更好的库实现.

最终,他们将其作为核心语言功能,因为他们没有别的选择:因为不可能做出足够好的库实现.

新的核心语言功能并不是简单地添加到语言中,因为它们似乎是个好主意.委员会非常不愿意添加它们,所讨论的功能确实需要证明自己.必须证明该功能是:

  • 可以在编译器中实现,
  • 要解决真正的需要,并且
  • 图书馆的实施不够好.

yield关键字的情况下,我们知道第一点可以解决.如您所示,这是一个相当简单的转换,可以通过机械方式完成.

第二点很棘手.有多少需要呢?存在的库实现有多广泛使用?有多少人要求这样做,或者为此提交了提案?

最后一点似乎也过去了.至少在C++ 03中,正如你所指出的那样,库实现会遇到一些缺陷,这可能证明核心语言的实现是合理的.可以在C++ 0x中实现更好的库实现吗?

所以我怀疑主要问题确实是缺乏兴趣.C++已经是一种庞大的语言,除非添加的功能非常值得,否则没有人希望它变得更大.我怀疑这只是不够用.


Dev*_*lar 8

添加关键字总是很棘手,因为它会使先前有效的代码无效.您试图在具有与C++一样大的代码库的语言中避免这种情况.

C++的发展是一个公共过程.如果您认为yield应该在那里,请向C++标准委员会提出适当的请求.

您将直接从做出决定的人那里得到答案.


小智 7

他们为lambdas做了这个,他们为什么不考虑支持产量呢?

检查文件.有人提出过吗?

......我只能猜测他们认为基于宏的实现是一个充分的替代品.

不必要.我确信他们知道存在这样的宏观解决方案,但是替换它们并不足以让新功能通过.


尽管围绕新关键字存在各种问题,但可以使用新语法克服这些问题,例如对lambdas执行并使用auto作为函数返回类型.

从根本上来说,新功能需要强大的驱动力(即人员)来通过委员会来全面分析和推动功能,因为他们总是会有很多人对激进的变革持怀疑态度.因此,即使没有你认为对抗收益率构造的强大技术理由,也可能仍然没有得到足够的支持.

但从根本上说,C++标准库已经采用了与使用yield看到的不同的迭代器概念.与Python的迭代器相比,它只需要两个操作:

  1. an_iter.next()返回下一个项目或引发包含在2.6中的StopIteration(next()内置而不是使用方法)
  2. iter(an_iter)返回an_iter(因此您可以在函数中处理相同的迭代和迭代器)

C++的迭代器成对使用(必须是相同的类型),分为类别,它将是一种语义转换,可以转换为更适合于yield构造的东西,并且这种转换不适合概念(具有自从被淘汰以来,但来得相对较晚).例如,见的(理直气壮,如果令人失望)拒绝我的评论改变基于范围for循环的形式,将使写这不同形式的迭代器容易得多.

具体说明我对不同迭代器形式的含义:生成的代码示例需要另一种类型作为迭代器类型以及用于获取和维护这些迭代器的相关机制.并不是说它无法处理,但它并不像你最初想象的那么简单.真正的复杂性是关于"局部"变量(包括构造期间)的异常的"简单转换",控制生成器内局部范围内的"本地"变量的生命周期(大多数需要跨调用保存),等等.

  • 致辞:"查看论文.有人提议吗?" - 好吧,如果C++委员会中没有人意识到协同程序/产量的好处(例如在重型套接字服务器,LINQ样式查询等中的最佳异步工作),难怪其他语言正在占据上风,让C++逐渐灭绝.至于迭代器,它们不一定是这个讨论的一部分 - 在没有迭代器的情况下,yield本身就好了,作为返回结果的另一种方式.我没有发表评论空间 - 而且很多人都相信即使是明显的事情,比如收益率,对于委员会的思考也是"超出范围"的. (5认同)
  • @ttsiodras:看看那些文章,以及进入它们的东西.委员会思考范围不大.如果你加入委员会并推动像"收益率"这样的事情,并努力使其在语言中运作并倾听其他人的反对意见,那么它将符合下一个标准.这就像其他人的宠物功能一样,没有被包括在内. (4认同)
  • @ttsiodras:迭代器是标准库的核心功能,但被视为语言核心的一个特性(例如,查看基于0x范围的for循环;以及为什么它们被设计为指针的超集).我认为任何与C++的迭代器概念不兼容的生成器/产量的提议都会被要求修改以实现它. (3认同)
  • @ttsiodras:我在这里显然不清楚:"宠物功能"并不是指某些无用的东西,或者你创造的东西,而是一种你真正想要的编程语言功能.例如,在COBOL讨论中,我的宠物特征是用户定义的函数,它返回一个值,这显然是有用的,显然不是我的想法,并且存在于比`yield`更多的编程语言中.不同的人有不同的宠物特征,其中大部分都是有用的.既然他们都努力做到正确,没有人想要增加太多,有些人会被排除在外. (2认同)

Ati*_*ifm 7

所以看起来它没有进入C++ 11或C++ 14,但可能正在进入C++ 17.看一下C++ Coroutines的演讲,CppCon2015的负面开销抽象这里的论文.

总而言之,他们正在努力扩展c ++函数以获得收益并等待函数的功能.看起来他们在Visual Studio 2015中有一个初始实现,不确定clang是否还有一个实现.它似乎也可能是使用yield并等待作为关键字的一些问题.

演示文稿很有意思,因为他谈到了简化网络代码的程度,等待数据进入以继续处理的顺序.令人惊讶的是,看起来使用这些新的协同程序会产生比现在更快/更少的代码.这是一个很棒的演讲.

可在此处找到C++的可恢复功能提议.