[英]Higher order function « filter » in C++
I wanted to write a higher order function filter
with C++. 我想用C ++编写一个更高阶的函数filter
。 The code I have come up with so far is as follows: 我到目前为止提出的代码如下:
#include <iostream>
#include <string>
#include <functional>
#include <algorithm>
#include <vector>
#include <list>
#include <iterator>
using namespace std;
bool isOdd(int const i) {
return i % 2 != 0;
}
template <
template <class, class> class Container,
class Predicate,
class Allocator,
class A
>
Container<A, Allocator> filter(Container<A, Allocator> const & container, Predicate const & pred) {
Container<A, Allocator> filtered(container);
container.erase(remove_if(filtered.begin(), filtered.end(), pred), filtered.end());
return filtered;
}
int main() {
int const a[] = {23, 12, 78, 21, 97, 64};
vector<int const> const v(a, a + 6);
vector<int const> const filtered = filter(v, isOdd);
copy(filtered.begin(), filtered.end(), ostream_iterator<int const>(cout, " "));
}
However on compiling this code, I get the following error messages that I am unable to understand and hence get rid of: 但是,在编译此代码时,我收到以下错误消息,我无法理解,因此摆脱:
/usr/include/c++/4.3/ext/new_allocator.h: In instantiation of ‘__gnu_cxx::new_allocator<const int>’:
/usr/include/c++/4.3/bits/allocator.h:84: instantiated from ‘std::allocator<const int>’
/usr/include/c++/4.3/bits/stl_vector.h:75: instantiated from ‘std::_Vector_base<const int, std::allocator<const int> >’
/usr/include/c++/4.3/bits/stl_vector.h:176: instantiated from ‘std::vector<const int, std::allocator<const int> >’
Filter.cpp:29: instantiated from here
/usr/include/c++/4.3/ext/new_allocator.h:82: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const [with _Tp = const int]’ cannot be overloaded
/usr/include/c++/4.3/ext/new_allocator.h:79: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const int]’
Filter.cpp: In function ‘Container<A, Allocator> filter(const Container<A, Allocator>&, const Predicate&) [with Container = std::vector, Predicate = bool ()(int), Allocator = std::allocator<const int>, A = const int]’:
Filter.cpp:30: instantiated from here
Filter.cpp:23: error: passing ‘const std::vector<const int, std::allocator<const int> >’ as ‘this’ argument of ‘__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> > std::vector<_Tp, _Alloc>::erase(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, __gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >) [with _Tp = const int, _Alloc = std::allocator<const int>]’ discards qualifiers
/usr/include/c++/4.3/bits/stl_algo.h: In function ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = __gnu_cxx::__normal_iterator<const int*, std::vector<const int, std::allocator<const int> > >, _Predicate = bool (*)(int)]’:
Filter.cpp:23: instantiated from ‘Container<A, Allocator> filter(const Container<A, Allocator>&, const Predicate&) [with Container = std::vector, Predicate = bool ()(int), Allocator = std::allocator<const int>, A = const int]’
Filter.cpp:30: instantiated from here
/usr/include/c++/4.3/bits/stl_algo.h:821: error: assignment of read-only location ‘__result.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = const int*, _Container = std::vector<const int, std::allocator<const int> >]()’
/usr/include/c++/4.3/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::deallocate(_Tp*, size_t) [with _Tp = const int]’:
/usr/include/c++/4.3/bits/stl_vector.h:150: instantiated from ‘void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(_Tp*, size_t) [with _Tp = const int, _Alloc = std::allocator<const int>]’
/usr/include/c++/4.3/bits/stl_vector.h:136: instantiated from ‘std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = const int, _Alloc = std::allocator<const int>]’
/usr/include/c++/4.3/bits/stl_vector.h:286: instantiated from ‘std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = const int*, _Tp = const int, _Alloc = std::allocator<const int>]’
Filter.cpp:29: instantiated from here
/usr/include/c++/4.3/ext/new_allocator.h:98: error: invalid conversion from ‘const void*’ to ‘void*’
/usr/include/c++/4.3/ext/new_allocator.h:98: error: initializing argument 1 of ‘void operator delete(void*)’
/usr/include/c++/4.3/bits/stl_algobase.h: In function ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = const int*, _OI = const int*]’:
/usr/include/c++/4.3/bits/stl_algobase.h:435: instantiated from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = __gnu_cxx::__normal_iterator<const int*, std::vector<const int, std::allocator<const int> > >, _OI = __gnu_cxx::__normal_iterator<const int*, std::vector<const int, std::allocator<const int> > >]’
/usr/include/c++/4.3/bits/stl_algobase.h:466: instantiated from ‘_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<const int*, std::vector<const int, std::allocator<const int> > >, _OI = __gnu_cxx::__normal_iterator<const int*, std::vector<const int, std::allocator<const int> > >]’
/usr/include/c++/4.3/bits/vector.tcc:136: instantiated from ‘__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> > std::vector<_Tp, _Alloc>::erase(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, __gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >) [with _Tp = const int, _Alloc = std::allocator<const int>]’
Filter.cpp:23: instantiated from ‘Container<A, Allocator> filter(const Container<A, Allocator>&, const Predicate&) [with Container = std::vector, Predicate = bool ()(int), Allocator = std::allocator<const int>, A = const int]’
Filter.cpp:30: instantiated from here
/usr/include/c++/4.3/bits/stl_algobase.h:396: error: no matching function for call to ‘std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m(const int*&, const int*&, const int*&)’
Please tell me what I am doing wrong here and what is the correct way to achieve the kind of higher order polymorphism I want. 请告诉我我在这里做错了什么,以及实现我想要的那种高阶多态的正确方法是什么。
Thanks. 谢谢。
EDIT: 编辑:
Thank you, everyone. 谢谢大家。 Here's the new code I got after applying your suggestions (and it works now, yay!) 这是我在应用你的建议后得到的新代码(它现在可以使用了,是的!)
#include <iostream>
#include <string>
#include <functional>
#include <algorithm>
#include <vector>
#include <list>
#include <iterator>
using namespace std;
bool isOdd(int const i) {
return i % 2 != 0;
}
template <
template <typename, typename> class Container,
typename Predicate,
typename Allocator,
typename A
>
Container<A, Allocator> filter(Container<A, Allocator> const & container, Predicate const & pred) {
Container<A, Allocator> filtered(container);
filtered.erase(remove_if(filtered.begin(), filtered.end(), pred), filtered.end());
return filtered;
}
int main() {
int a[] = {23, 12, 78, 21, 97, 64};
vector<int> v(a, a + 6);
vector<int> filtered = filter(v, isOdd);
copy(filtered.begin(), filtered.end(), ostream_iterator<int>(cout, " "));
}
Why is your Container
parametrized at all? 为什么Container
参数化了?
template <typename C, typename P>
C filter(C const & container, P pred) {
C filtered(container);
filtered.erase(remove_if(filtered.begin(), filtered.end(), pred), filtered.end());
return filtered;
}
Works just as well. 也适用。 Notice that I passed P
by value rather than by const reference, as advised by Meyers in Effective C++ (iterators and functors should be passed by value). 请注意,我通过值传递P
而不是const引用,正如Meyers在Effective C ++中所建议的那样(迭代器和仿函数应该通过值传递)。
what about remove_copy_if instead ? 那么remove_copy_if呢? (with isEven()). (使用isEven())。 It's already built for you. 它已经为你而建。
The error is not in filter
, but in: 错误不在filter
,而是在:
int main() {
int const a[] = {23, 12, 78, 21, 97, 64};
vector<int const> const v(a, a + 6);
}
You can't have a vector of const stuff . 你不能拥有const的东西 。 Remove the inner const: 删除内部const:
int main() {
int const a[] = {23, 12, 78, 21, 97, 64};
vector<int> const v(a, a + 6);
}
(And of course, filtered.erase
, not container.erase
.) (当然, filtered.erase
,而不是container.erase
。)
container
is a const-reference. container
是一个const引用。 You can't call erase()
on it. 你不能在上面调用erase()
。 You probably mean to call 你可能打算打电话
filtered.erase(remove_if(filtered.begin(), filtered.end(), pred), filtered.end());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.