C++ 范围像 Java 流一样查找并返回 std::optional

标签 c++ c++20 stdoptional

在 Java 中, Stream.findFirst() returns Optional<T> .我希望对 std::ranges::find() 有类似的行为.如果未找到该值,则返回 last迭代器。如果 T 这很不方便是一个结构,我试图从中获取一个成员。这是一个演示代码:

    struct Person {
        int age;
        int height;
    };

    std::vector<Person> people;
    people.emplace_back(20, 100);
    people.emplace_back(23, 170);

    // find the height of a 23yo person
    std::optional<int> height1 = std::ranges::find(people, 23, &Person::age)->height;

    // find the height of a 26yo person
    std::optional<int> height2 = std::ranges::find(people, 26, &Person::age)->height;  // error

当然我可以在每个 find 周围放置一些包装代码转换迭代器,但它使代码如此冗长和样板。我想知道 C++20 中是否有一些更惯用的方法来做到这一点?

    std::optional<int> height2;
    auto iter = std::ranges::find(people, 26, &Person::age);
    if (iter == people.end()) {
        height2 = std::nullopt;
    } else {
        height2 = iter->height;
    }

最佳答案

template <class ...ArgsT>
auto OpRangesFind(auto &&Range, ArgsT &&...Args)
{
    auto Iter = std::ranges::find(Range, std::forward<ArgsT>(Args)...);
    return Iter != Range.end() ? Iter : std::optional<decltype(Iter)>{std::nullopt};
}

int main()
{
    /* ... */

    auto OpIter = OpRangesFind(people, 26, &Person::age);
    if (!OpIter.has_value()) {
        std::cout << "not found\n";
    } else {
        std::cout << "found\n";
        std::cout << "height: " << OpIter.value()->height << "\n";
        //                               ^^^^^^^^
    }
}

关于C++ 范围像 Java 流一样查找并返回 std::optional,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65384273/

相关文章:

C++ extern const char* 没有按预期工作

c++ - 与 std::lower_bound 相比,ranges::lower_bound 是否有不同的比较要求?

c++ - 我如何在 C++ 中使用 std::optional?

c++ - C++中的三元运算符生成什么对象?

c++ - sizeof 是否可以在 lambda 中应用于未捕获的变量,或者这是一个编译器错误?

c++无法使选择排序正常工作

c++ - Qt - 使用lambda函数修改先前连接信号的槽参数

c++ - memory_order_seq_cst 和 memory_order_release 的可能排序

c++ - 非模板函数上的约束表达式有什么意义?

c++ - 在 noexcept 函数体中处理 std::optional 是否安全?