简体   繁体   English

定义自定义迭代器,将调用函数的元素传递给传递的元素

[英]Define custom iterator that calls function to passed element

I am often writing code like the following (here int and double are just example, types are usually pointers) 我经常在编写如下代码(这里的int和double只是示例,类型通常是指针)

std::vector<int> va {1 ,2, 3};
std::vector<double> vb;

bool valid(int i) { return i % 2 == 0;}

for(auto a : va)
   if (valid(a))
      vb.push_back(static_cast<double>(a));

Since we don't have transform_if I would like to know if there is a way to do this by definining some special iterator: 由于我们没有transform_if所以我想知道是否有办法通过定义一些特殊的迭代器来做到这一点:

template<typename T>
struct inserterStaticCast
{
    // not sure what to put here...
}

Then I could write code like 然后我可以写像

std::vector<double> vc(a.size());
std::copy_if(a.begin(), a.end(), inserterStaticCast<double>(vc), &valid);

I would also be interested in the backInserterStaticCast version. 我也会对backInserterStaticCast版本感兴趣。

Is this possible in C++11? 在C ++ 11中可能吗?

Thank you 谢谢

A few clarifications... 一些澄清...

I cannot use boost. 我不能使用升压。 And to again in this case int and double are just for illustration, in the general case I do need a cast, usually something like static_cast<derived *>(base_ptr) . 再次在这种情况下,int和double只是为了说明,在一般情况下,我确实需要static_cast<derived *>(base_ptr) ,通常类似于static_cast<derived *>(base_ptr)

I think you want boost's function_output_iterator . 我认为您需要boost的function_output_iterator In your example it would be 在您的示例中

auto cast_back_iterator = make_function_output_iterator([&b](int i){ b.push_back(static_cast<double>(i)); });
std::copy_if(a.begin(), a.end(), cast_back_iterator, valid);

Which makes more sense when there isn't an implicit conversion between the two types, such as with Base * -> Derived * conversion 当两种类型之间没有隐式转换时,例如使用Base * -> Derived *转换,这更有意义

You can do filtering with std::copy_if and std::back_inserter : 您可以使用std::copy_ifstd::back_inserter进行过滤:

std::vector<double> vc;
std::copy_if(va.begin(), va.end(), std::back_inserter(vc), valid);

Or use boost::range::adaptors::filtered (same example problem as yours): 或使用boost::range::adaptors::filtered (与您的示例问题相同):

#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>

#include <vector>

bool valid(int i) { return i % 2 == 0;}

int main() {
    std::vector<int> va {1 ,2, 3};

    using namespace boost::adaptors;
    auto vb = boost::copy_range<std::vector<double>>(va | filtered(valid));
}

Note that conversion of int to double is implicit and doesn't require a cast. 请注意,将int转换为double是隐式的,不需要强制转换。

If you do need a conversion, just throw in transformed : 如果确实需要转换,则只需输入transformed

auto vb = boost::copy_range<std::vector<double>>(va
    | filtered(valid)
    | transformed([](int a) { return static_cast<double>(a); })
    );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM