std::find_if 中的 Predictor 仿函数不是引用

问题描述 投票:0回答:1

以下是

std::find_if

的定义
template< class InputIt, class UnaryPredicate >
constexpr InputIt find_if( InputIt first, InputIt last, UnaryPredicate p );

为什么不使用

UnaryPredicate&& p
作为参数?

如果我的谓词很难复制,我该怎么办?

以下情况是否应该区别对待?

  1. UnaryPredicate::operator()
    是 const 合格的(通常应该是这样)
  2. UnaryPredicate::operator()
    不是 const 合格的。
  3. 具有以下超载:
    UnaryPredicate::operator() &&
    (看到这很疯狂吗?)我将传递一个右值作为预测变量。
c++ rvalue-reference
1个回答
1
投票

大多数谓词的复制成本很低,所以这通常不是问题。

如果你有一个复制起来真的很昂贵,你可以(经常)使用

std::reference_wrapper
来提供一个复制起来很便宜的包装器。这是一个快速演示:

#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <chrono>

using namespace std::literals;

struct Predicate {

    Predicate() = default;
    Predicate(Predicate const &) { std::this_thread::sleep_for(1s); }

    bool operator()(int i) const { return i == 10; }
};

int main() { 
    Predicate p;

    using namespace std::chrono;

    std::vector<int> foo { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    auto start = high_resolution_clock::now();
    auto pos1 = std::find_if(foo.begin(), foo.end(), p);
    auto mid = high_resolution_clock::now();   
    auto pos = std::find_if(foo.begin(), foo.end(), std::ref(p));
    auto end = high_resolution_clock::now();

    std::cout << pos - foo.begin() << '\n';
    std::cout << pos1 - foo.begin() << '\n';

    std::cout << "bare: " << duration_cast<seconds>(mid-start).count() << " s\n";
    std::cout << "wrap: " << duration_cast<nanoseconds>(end-mid).count() << " ns\n";
}

当我运行它时,我得到这样的输出:

9
9
bare: 5 s
wrap: 168 ns

因此,看起来正在制作 5 个副本。使用“裸”

Predicate
对象时,搜索需要 5 秒。使用wrapped的时候,需要168纳秒(包括搜索,不只是复制
Predicate
)。

我相信应该与

operator()
一起工作,无论
const
合格与否。我还没有检查右值引用合格版本,但我很确定这需要更多工作(
reference_wrapper
明确删除
ref(&&)
,这可能是有充分理由的,所以支持右值引用可能很重要) .

© www.soinside.com 2019 - 2024. All rights reserved.