【问题标题】:How to implement copy_if in terms of std::remove_copy_if?如何根据 std::remove_copy_if 实现 copy_if?
【发布时间】:2011-04-28 21:56:50
【问题描述】:

我已经制定了一个在大多数情况下都有效的解决方案:

#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 ref 参数。这会导致以下编译器错误:

/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. 根据 std::remove_copy_if 实现
  2. 必须使用函数对象和函数指针
  3. 不定义辅助类(在函数范围之外)
  4. 使用纯 C++ 和 STL(无 C++0x 或 boost)

更新

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

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));
}

【问题讨论】:

  • @sbi 那篇文章没有提供一个解决方案,它根据 remove_copy_if 实现 copy_if 并且适用于函数指针和函数对象。
  • 有什么特殊原因不能在 copy_if 的主体中写出循环吗?为什么您必须使用 remove_copy_if?
  • @AshleysBrain:我只是想看看有没有可能。
  • @Stacked: IIUC, stackoverflow.com/questions/1448817/… 确实提供了解决方案。

标签: c++ stl stl-algorithm


【解决方案1】:

对于 C++03 &lt;functional&gt; 来说不同寻常的是,您所做的工作有点太多。删除 Adapter 以支持工厂函数。

http://ideone.com/2VEfH

// 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。我已经在这个 sn-p 中修复了它。

【讨论】:

  • 你应该返回out(即返回remove_copy_if()
  • 有趣。但是,提供的代码在使用带有 const 引用的函数指针调用它时会导致相同的编译器错误:`错误:形成对引用类型'const int&'的引用。
  • @Stacked:我很困惑。我用is_odd_const_ref 解决了这个问题,您还有其他可以发布到该问题的案例吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
  • 2010-11-29
  • 1970-01-01
  • 2013-11-01
相关资源
最近更新 更多