【问题标题】:Why does std::foreach not work with a std::vector<bool>? [duplicate]为什么 std::foreach 不能与 std::vector<bool> 一起使用? [复制]
【发布时间】:2018-11-08 00:27:41
【问题描述】:

我有以下代码 sn-p,它采用 std::vector&lt;int&gt; list 并在所有向量元素中写入零。这个例子工作得很好。

#include <vector>
#include <iostream>
#include <algorithm>

int main () {
    std::vector<int> list {1, 1, 2};
    auto reset = [](int & element){element = 0;};

    auto print = [](int element) {std::cout << element << " ";};
    std::for_each(list.begin(), list.end(), reset);
    std::for_each(list.begin(), list.end(), print);
}

如果我将向量的类型从int 更改为bool,代码将无法编译。

#include <vector>
#include <iostream>
#include <algorithm>

int main () {
    std::vector<bool> list {true, true, false};
    auto reset = [](bool & element){element = false;};

    auto print = [](int element) {std::cout << element << " ";};
    std::for_each(list.begin(), list.end(), reset);
    std::for_each(list.begin(), list.end(), print);
}

https://godbolt.org/g/2EntgX

我不明白编译器错误信息:

/opt/compiler-explorer/gcc-7.2.0/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/ bits/stl_algo.h:3884:2: 错误: 没有匹配函数调用类型为 '(lambda at :7:18)'

    __f(*__first);

    ^~~

:10:10: 注意:在函数模板的实例化中 专业化 'std::for_each:7:18)>' 在这里请求

std::for_each(list.begin(), list.end(),reset);

     ^

:7:18: 注意:候选函数不可行:未知 从 'std::_Bit_iterator::reference' 转换(又名 'std::_Bit_reference') 到 'bool &' 作为第一个参数

auto reset = [](bool & element){element = false;};

             ^

:7:18: 注意:'void (*)(bool &)' 类型的转换候选

为什么std::foreach 可以与std::vector&lt;int&gt; 一起使用,但不能与std::vector&lt;bool&gt; 一起使用?

std::vector&lt;bool&gt;(见here)的内存优化是答案的一部分吗?

【问题讨论】:

  • std::vector&lt;bool&gt; 的迭代器类型在取消引用时不返回 bool&amp;。相反,它返回一个代理对象。使用auto&amp; 而不是bool&amp; 来获取代理。
  • @Incomputable:请不要将答案放在 cmets 部分。

标签: c++ vector foreach boolean


【解决方案1】:

原因

问题源于取消引用来自std::vector&lt;bool&gt; 的迭代器不会返回bool&amp;,而是返回一个代理对象。因此,it is not regarded as stl container(感谢@KillzoneKid)。

修复

在参数列表中使用auto element。一般来说,如果你不关心类型,在 lambda 参数列表中使用auto&amp;&amp;

#include <vector>
#include <iostream>
#include <algorithm>

int main () {
    std::vector<bool> list {true, true, false};
    auto reset = [](auto && element){element = false;};

    auto print = [](int element) {std::cout<< element << " ";};
    std::for_each(list.begin(), list.end(),reset);
    std::for_each(list.begin(), list.end(),print);

}

Demo.

尝试使用auto&amp;trigger compilation error again,因为返回的代理不是左值,而是右值。因此,auto&amp;&amp; 的好处比平时更多。

【讨论】:

  • 酷。类型推断在这里究竟是如何工作的?
  • @leftaroundabout,我不确定,但由于std::vector&lt;bool&gt;::reference是用户定义的类型,取消引用将返回非引用,因此复制代理不会造成任何伤害。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-05
  • 2017-11-10
  • 1970-01-01
  • 2018-02-17
  • 1970-01-01
  • 2019-07-09
相关资源
最近更新 更多