Re: STL algorithm member function problem
In article <1163606212.511853.245150@h48g2000cwc.googlegroups.com>,
<lists@givemefish.com> wrote:
Hi all,
I have an application that works on a series of file names stored in a
vector<string>.
I have a set of rules that I want to apply to that list to narrow the
list down. Each rule operates on a single file name, and it determine
whether the filename should remain or be removed from the list of
filenames. There are several different types of rules, each inherited
from a base class Rule, which is inherited from unary_function. The
list of rules is stored in a vector as boost shared_ptr objects of type
Rule*.
I want to iterate over all the rules in the list and apply them to the
filename list using the remove_if algorithm. But I am having trouble
with the remove_if call.
Thus the code looks something like this:
class Rule : public std::unary_function<std::string, bool> {
public:
virtual result_type operator()(const argument_type&) const =0;
};
typedef boost::shared_ptr<Rule> RulePtr;
///////////////
// Concrete rules are inherited from the Rule class and define
// the operator()
.....
vector<string> fileList;
// .... fill fileList with a series of file names ...
//Now remove items from the fileList according to the rules.
//Iterate over all the rules in the rules vector. Apply the rule
to each of
// items in the fileList and remove it if the rule returns true.
for(vector<RulePtr>::const_iterator ruleIter = m_rules.begin();
ruleIter != m_rules.end(); ++ruleIter) {
// This is the problem line...
std::remove_if(fileList.begin(), fileList.end(), ptr_fun(
xxx );
}
Can someone help me with the correct syntax for the remove_if function?
I can't seem to get it right.
remove_if does not remove anything that is fileLIst.size() [before
remove_if(...) ] is equal to fileList.size() [after remove_if(...)]
remove_if returns an iterator so that
[fileList.begin(),result_of_remove_if) is a range containing the non
removed items and [result_of_remove_if,fileList.end()) is garbage.
if you want to really remove the garbage then
fileList.erase
(
std::remove_if(fileList.begin(),fileList.end(),pred),
fileList.end()
);
actually removes the items satisfying pred. that is those
whose for which pred returns true.
struct remove_by_rule
{
std::vector<std::string> &fileList;
remove_by_rule(std::vector<std::string> &a):fileList(a){}
void operator () (RulePtr p)
{
fileList.erase
(
std::remove_if(fileList.begin(),fileList.end(),*p),
fileList.end()
);
}
};
int main()
{
// ...
std::for_each(m_rules.begin(),m_rules.end(),
remove_rule(fileList) );
// ...
}
easier to read in my opinion and avoids explicitly naming iterator
types for iterators local to the loops actually performed. Holding
a non constant reference in the functor remove_by_rule assures the
same vector will be used no matter how many copies of remove_by_rule
are preformed and those copies will be 'cheap'. It also avoids copying
after the for_each() is performed.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]