【问题标题】:Using the value that any_of finds to use in a return outside lambda使用 any_of 找到的值在 lambda 之外的返回中使用
【发布时间】:2016-09-01 04:17:00
【问题描述】:

一段工作代码:

std::vector<double>::iterator it = std::find_if(intersections.begin(), intersections.end(), [&](const double i) {return i >= 0;});
if (it != intersections.end())
    return rayOrigin + *(it) * rayDirection);

但我想用这样的东西

有没有办法以干净的方式(不使用临时变量)捕获 i,any_of 在这里找到并在 return 语句中使用它

if (std::any_of(intersections.begin(), intersections.end(), [&](const double i) {return i >= 0;}))
    return rayOrigin + i * rayDirection);

【问题讨论】:

    标签: c++ c++11 lambda


    【解决方案1】:

    我会编写一个基于范围的搜索器,它返回一个对象,该对象可以被 * 取消引用(可能不止一次)以获取找到的东西,或者在 bool 上下文中评估以确定是否找到它。

    根据我的经验,这使代码更简洁,并使“我想知道它是否存在”的常见情况更简单,但允许您简洁地了解项目:

    template<class Range, class F>
    auto linear_search_if( Range&& r, F&& f )
    // remove next line in C++14, it removes ADL `begin` capability:
    -> typename std::iterator_traits<decltype( std::begin(r) )>::value_type*
    // reproducing ADL begin in C++11 is a pain, so just use the above line
    {
      using std::begin;  using std::end;
      using iterator = decltype(begin(r));
      using T = typename std::iterator_traits<iterator>::value_type;
      using R = T*; // in C++17 I prefer std::optional<iterator>;
      iterator it = std::find_if( begin(r), end(r), std::forward<F>(f) );
      if (it != end(r))
        return R(std::addressof(*it)); // return R(it); in C++17
      else
        return R(nullptr); // return R{}; in C++17
    }
    
    if (auto pi = linear_search_if( intersections, [&](auto i){return i>=0;})
      return rayOrigin + *pi * rayDirection; // **pi in C++17
    

    是的,您使用*pi 而不仅仅是i

    【讨论】:

    • 可能有更多的解释..? “你喜欢”?
    • @Ven 是的,在 C++17 中,我个人更愿意在这样的函数中返回 optional&lt;iterator&gt; 而不是 T*?我可以继续解释为什么我更喜欢它,但这与解决方案无关。
    • 如果是,为什么要在这里包含它?
    • @Ven 当我编写代码供他人学习时,我试图让它值得效仿?而在 C++17 中,可选的解决方案是一个更好的解决方案。 C++17 基本就到这里了,我不想鼓励人们在optional&lt;iterator&gt; 更好的时候使用T*。通过提到它是一个更好的选择,如果他们有 C++17 编译器,他们可能会模仿它并产生比我没有提到它的情况更好的代码。
    • 如果你只想说“这个解决方案是最好的解决方案™”但没有解释原因,那么我会说“不要”
    【解决方案2】:

    是的,find_ifany_of 的当前方式有点烦人。 @Yakk 的解决方案通过在 std::find_if 周围编写一个包装器来工作,该包装器返回一个 std::optional&lt;int&gt; 来测试成功并有条件地提取结果。这无疑是下一个 STL 版本的前进方向。

    但是,在 C++17 中,您可以move initializers into selection statements 已经消除了大部分痛苦:

    #include <algorithm>
    #include <iostream>
    #include <vector>
    
    int main()
    {
        auto const v = std::vector<int> { -2, -1, 0, 1, 2 };
        auto const pred = [&](const int i) { return i >= 0; };
    
        if (auto const it = std::find_if(v.begin(), v.end(), pred); it != v.end())
            std::cout << *it << '\n';      
    }
    

    Live Example 在 c++1z 模式下使用最近的 Clang。

    【讨论】:

      猜你喜欢
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多