【问题标题】:Is std::remove_if with lambda predicate and auto element possible?可以使用带有 lambda 谓词和 auto 元素的 std::remove_if 吗?
【发布时间】:2011-09-14 07:54:27
【问题描述】:

我假设这是不可能的,因为我收到以下错误:

error C3533: 'auto': a parameter cannot have a type that contains 'auto'

这是重现错误的代码 sn-p:

int myInts[] = {1,2,3,3,3,4};
std::vector<int> myVec(myInts, myInts + sizeof(myInts)/sizeof(int));
myVec.erase(
    std::remove_if(myVec.begin(), myVec.end(),
        [](auto i){return i==3;}), // lambda param error
    myVec.end());

现在如果你写这个,一切都很好,它会删除值为 3 的元素:

int myInts[] = {1,2,3,3,3,4};
std::vector<int> myVec(myInts, myInts + sizeof(myInts)/sizeof(int));
myVec.erase(
    std::remove_if(myVec.begin(), myVec.end(),
        [](int i){return i==3;}),
    myVec.end());

那么你能不能像错误提示的那样直接不使用auto作为函数参数?

这是因为auto 的类型是由编译器无法推断出的右值 确定的,尽管它是在int 的已知向量上执行的算法的谓词?

有人知道原因吗?

【问题讨论】:

  • Herb Sutter 最近在第 9 频道谈到了这个问题。channel9.msdn.com/Shows/Going+Deep/…
  • 如果我能在没有缓冲的情况下超过 4 秒,那可能会非常有趣。
  • 下载链接在右边。
  • 在 C++14 中,引入了通用 lambdas (1, 2),允许使用 auto

标签: c++ stl lambda c++11


【解决方案1】:

遗憾的是,虽然这是在 C++0x 过程中提出的,但最终没有成功。对于简单的函子,您可能想要使用类似 Boost.Lambda 之类的东西(也许凤凰 v3 出来时也是如此),其中生成的函子是多态的(因此您无需指定任何内容):

std::remove_if(myVec.begin(), myVec.end(),
    _1 == 3)

只有类型推断的解决方案:

// uses pass-by-reference unlike the question
std::remove_if(myVec.begin(), myVec.end(),
    [](decltype(myVec[0]) i){return i==3;})

【讨论】:

  • 最后我听说,Boost.Phoenix v3 是 Boost.Lambda(最终是 Boost.Bind)的官方替代品,所以鉴于 Boost.Lambda 没有未来,最好从 Phoenix v2 开始(或等待 v3)并完全忽略 Boost.Lambda。
  • nifty,我们使用 boost,所以这是一个选择,但我最近一直在尝试熟悉 C++0x 功能。
  • @AJG86 没有允许动态创建多态仿函数的 C++0x 功能——尽管您的特定问题只需要解决类型推断,而不是完整的多态性
【解决方案2】:

auto 是基于您将其初始化为的值的类型推断。参数未在代码中出现的位置初始化为任何内容。

【讨论】:

  • 我在函数中默认 auto 参数的值时遇到了同样的错误,所以我猜这还不够,但这是意料之中的。
【解决方案3】:

基本上,这已经被建议了,然后被拒绝了,并且 then lambdas被添加了,所以它几乎成功但碰巧没有,并且很可能将它变成语言未来。

【讨论】:

  • 任何对历史性讨论的参考都会很棒。知道在哪里可以找到一些档案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
  • 2017-12-11
  • 2014-03-23
  • 1970-01-01
  • 2016-12-14
相关资源
最近更新 更多