使用 lambda 谓词和 auto 元素的 std::remove_if 是否可行?

6
我认为这是不可能的,因为我收到了以下错误消息:
error C3533: 'auto': a parameter cannot have a type that contains 'auto'

以下是一个代码片段,可以重现错误:
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的类型由编译器无法推断的rvalue决定,尽管它是在已知int向量上执行的算法的谓词?

有人知道原因吗?


Herb Sutter最近在Channel 9上谈到了这个问题。http://channel9.msdn.com/Shows/Going+Deep/Herb-Sutter-C-Questions-and-Answers - Benjamin Lindley
如果我能在不缓冲的情况下坚持4秒钟,那可能会非常有趣哈哈。 - AJG85
下载链接在右侧。 - Benjamin Lindley
在C++14中引入了通用lambda表达式(1, 2),允许使用auto - Roi Danton
3个回答

8

auto是一种基于所初始化的值进行类型推断的方式。参数在代码中出现的位置上并没有被初始化。


当我在函数中将auto参数的值设为默认值时,我会得到相同的错误,所以我猜这还不够,但这也是意料之中的。 - AJG85

8

遗憾的是,在C++0x过程中建议了这个功能,但最终未能实现。对于简单的函数对象,您可能想使用类似于Boost.Lambda(也许是Phoenix 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;})

1
据我所知,Boost.Phoenix v3是Boost.Lambda(最终也包括Boost.Bind)的官方替代品,因此考虑到Boost.Lambda没有未来,最好从Phoenix v2开始(或等待v3),并完全忽略Boost.Lambda。 - ildjarn
很棒,我们使用boost,所以那是一个选项,但我最近一直在尝试熟悉C++0x的特性。 - AJG85
@AJG86 目前没有 C++0x 功能可以在运行时创建多态函数对象 -- 尽管你的特定问题只需要类型推断即可解决,而不需要完整的多态性。 - Luc Danton

2
基本上,这个建议已经被提出过,然后被拒绝了,然后添加了lambda表达式,所以它几乎成为了一部分,但最终未能实现,很可能在未来加入到语言中。

有关历史讨论的任何参考资料都很好。你知道在哪里可以找到一些档案吗? - Drew Noakes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接