首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用copy_if实现std::remove_copy_if?

如何用copy_if实现std::remove_copy_if?
EN

Stack Overflow用户
提问于 2011-04-28 21:56:50
回答 1查看 2.1K关注 0票数 2

我已经想出了一种解决方案,大部分时间都有效:

代码语言:javascript
复制
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

// Overload that takes a function pointer
template<class ForwardIterator, class OutputIterator, class ArgType>
void copy_if(ForwardIterator begin, ForwardIterator end, OutputIterator out, bool (*inPredicate)(ArgType))
{
    typedef std::pointer_to_unary_function<ArgType, bool> Adapter;
    std::remove_copy_if(begin, end, out, std::unary_negate<Adapter>(Adapter(inPredicate)));
}

// Overload that takes a function object
template<class ForwardIterator, class OutputIterator, class Functor>
void copy_if(ForwardIterator begin, ForwardIterator end, OutputIterator out, Functor inFunctor)
{
    std::remove_copy_if(begin, end, out, std::unary_negate<Functor>(inFunctor));
}

bool is_odd(int inValue)
{
    return inValue % 2 == 1;
}

bool is_odd_const_ref(const int & inValue)
{
    return inValue % 2 == 1;
}

struct is_odd_functor : public std::unary_function<int, bool>
{
    bool operator() (const int & inValue) const { return inValue % 2 == 1; }
};

int main()
{
    std::vector<int> numbers;
    numbers.push_back(0);
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);

    std::vector<int> copy;

    // Functor: Ok
    copy_if(numbers.begin(), numbers.end(), std::back_inserter(copy), is_odd_functor());

    // Function pointer: Ok
    copy_if(numbers.begin(), numbers.end(), std::back_inserter(copy), is_odd);

    // Function pointer that takes const ref: Compiler error
    copy_if(numbers.begin(), numbers.end(), std::back_inserter(copy), is_odd_const_ref);
    return 0;
}

它不起作用的唯一情况是函数指针采用const参数。这将导致以下编译器错误:

代码语言:javascript
复制
/usr/include/c++/4.2.1/bits/stl_function.h: In instantiation of ‘std::unary_negate<std::pointer_to_unary_function<const int&, bool> >’:
main.cpp:11:   instantiated from ‘void copy_if(ForwardIterator, ForwardIterator, OutputIterator, bool (*)(ArgType)) [with ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, OutputIterator = std::back_insert_iterator<std::vector<int, std::allocator<int> > >, ArgType = const int&]’
main.cpp:53:   instantiated from here
/usr/include/c++/4.2.1/bits/stl_function.h:322: error: forming reference to reference type ‘const int&’
/usr/include/c++/4.2.1/bits/stl_algo.h: In function ‘_OutputIterator std::remove_copy_if(_InputIterator, _InputIterator, _OutputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OutputIterator = std::back_insert_iterator<std::vector<int, std::allocator<int> > >, _Predicate = std::unary_negate<std::pointer_to_unary_function<const int&, bool> >]’:
main.cpp:11:   instantiated from ‘void copy_if(ForwardIterator, ForwardIterator, OutputIterator, bool (*)(ArgType)) [with ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, OutputIterator = std::back_insert_iterator<std::vector<int, std::allocator<int> > >, ArgType = const int&]’
main.cpp:53:   instantiated from here
/usr/include/c++/4.2.1/bits/stl_algo.h:1227: error: no match for call to ‘(std::unary_negate<std::pointer_to_unary_function<const int&, bool> >) (int&)’

显然,这里试图提及一项参考。

我的问题是:如何实现满足以下条件的copy_if

  1. implementation在std::remove_copy_if
  2. must方面使用函数对象和函数pointers
  3. without定义助手类(函数范围外)
  4. ,使用纯C++和STL (无C++0x或boost)

更新

我认为这是可能的,因为它适用于boost::bind

代码语言:javascript
复制
template<class ForwardIterator, class OutputIterator, class Functor>
void copy_if(ForwardIterator begin, ForwardIterator end, OutputIterator out, Functor inFunctor)
{
    std::remove_copy_if(begin, end, out, !boost::bind(inFunctor, _1));
}
EN

回答 1

Stack Overflow用户

发布于 2011-04-28 23:29:34

对于C++03 <functional>来说,不寻常的是,您做的工作太多了。消除Adapter,有利于工厂的功能。

http://ideone.com/2VEfH

代码语言:javascript
复制
// Overload that takes a function pointer
template<class ForwardIterator, class OutputIterator, class ArgType>
OutputIterator copy_if(ForwardIterator begin, ForwardIterator end, OutputIterator out, bool (*inPredicate)(ArgType))
{
    return std::remove_copy_if(begin, end, out, std::not1(std::ptr_fun(inPredicate)));
}

// Overload that takes a function object
template<class ForwardIterator, class OutputIterator, class Functor>
OutputIterator copy_if(ForwardIterator begin, ForwardIterator end, OutputIterator out, Functor inPredicate)
{
    return std::remove_copy_if(begin, end, out, std::not1(inPredicate));
}

另外,我要指出的是,应该将TR1添加到您决定不使用的公共设施列表中。

另外,如果函数指针copy_if重载称为函子重载,而不是两者都是完整的实现,那就更优雅了。

此外,正如@wilhelm所指出的,返回类型应该是OutputIterator。我在这个片段里把它修好了。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5825532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档