使用 for_each 提升 sub_range;为啥我得到一个常量引用?

Posted

技术标签:

【中文标题】使用 for_each 提升 sub_range;为啥我得到一个常量引用?【英文标题】:Boost sub_range with for_each; why am I getting a const-reference?使用 for_each 提升 sub_range;为什么我得到一个常量引用? 【发布时间】:2014-02-09 08:37:26 【问题描述】:

在 OS X Mavericks 上,使用 boost 1.55.0 和 clang-500.2.79(基于 LLVM 3.3svn),我正在尝试使用 boost::for_each 和 @987654323 迭代 std::map 中的子范围@。在我的函数对象中,我希望收到一个 std::pair &。相反,我似乎收到了一个 const std::pair &。为什么?

#include <map>
#include <boost/range/algorithm.hpp>
#include <boost/range/sub_range.hpp>

using std::map;
using std::begin;
using std::end;
using std::pair;
using boost::for_each;
using boost::sub_range;

int main()
   
    map<int, int> myMap;
    sub_range<decltype(myMap)> s
        begin(myMap),
        end(myMap)
    ;

    auto f1 = [&](const pair<int, int> &) 
    ;
    for_each(s, f1);    // Compiles fine

    auto f2 = [&](pair<int, int> &) 
    ;
    for_each(s, f2);    // Fails to compile


/Users/ambarish> clang++ main.cxx 
In file included from main.cxx:1:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/map:371:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__tree:18:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/algorithm:793:9: error: no matching function for call to object of type '<lambda at main.cxx:24:15>'
        __f(*__first);
        ^~~
/usr/local/include/boost/range/algorithm/for_each.hpp:80:12: note: in instantiation of function template specialization
      'std::__1::for_each<std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, int>, std::__1::__tree_node<std::__1::pair<int, int>, void *> *, long> >, <lambda at main.cxx:24:15> >'
      requested here
    return std::for_each<
           ^
main.cxx:26:5: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
    for_each(s, f2);
    ^
main.cxx:24:15: note: candidate function not viable: no known conversion from 'value_type' (aka 'pair<__key_type, __mapped_type>') to 'pair<int, int> &' for 1st argument
    auto f2 = [&](pair<int, int> &) 
              ^
1 error generated.

【问题讨论】:

【参考方案1】:

因为std::map&lt;int, int&gt;的值类型不是std::pair&lt;int,int&gt;而是std::pair&lt;const int, int&gt;,所以无法编译。

第一个 (f1) 编译的原因是因为std::pair 有这个构造函数:

template< class U1, class U2 >
pair( pair<U1, U2>&& p );

因为f1 通过 const 引用获取参数。现在有一个合适的转换可以生成一个可以轻松绑定到 const 引用的临时对象。

修复:

auto f2 = [&](pair<const int, int> &)  ;
// or
auto f2 = [&](pair<int, int>)  ;

【讨论】:

【参考方案2】:

代码似乎在 boost 库实现中使用 std::for_each,并且 C++11 风格的标准 lambdas 无论如何都被传递给 for_each 函数。这实际上取决于库如何将容器的迭代器传递给 std::for_each

【讨论】:

以上是关于使用 for_each 提升 sub_range;为啥我得到一个常量引用?的主要内容,如果未能解决你的问题,请参考以下文章

提升 lambda 函数调用

如何在 C++ 中使用 for_each 累积结果? [复制]

使用具有 for_each 集的模块的输出值

for_each使用

STL经常使用遍历算法for_each和transform的比較

使用 terraform 在 for_each 嵌套资源中循环