1

I can't find what I'm doing wrong here. The function eta does what I ask but when I use it in the loop I get the attached error.

bool eta(map<string, TLorentzVector> map_jets, string jet){
    return(  fabs(map_jets[jet].PseudoRapidity()) > 2.5 );
}

and then

vector<pair<string,double> > jets_pt( vec_jets.size() );

    for( vector<pair<string,double> >::iterator it = jets_pt.begin(); it != jets_pt.end(); ++it)
jets_pt.erase(remove_if(jets_pt.begin(),jets_pt.end(),eta(map_jets,it1->first)),jets_pt.end);

I get the error

/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function '_OutputIterator std::remove_copy_if(_InputIterator, _InputIterator, _OutputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _OutputIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]':
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1291:   instantiated from '_ForwardIterator std::remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]'
/misc/cdf/gbertoli/hww/Diboson_v20_taus/Ana/src/Functions.cc:25:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1216: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]':
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:338:   instantiated from '_InputIterator std::find_if(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1287:   instantiated from '_ForwardIterator std::remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]'
/misc/cdf/gbertoli/hww/Diboson_v20_taus/Ana/src/Functions.cc:25:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:260: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:264: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:268: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:272: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:280: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:284: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:288: error: '__pred' cannot be used as a function
mv: cannot stat `/misc/cdf/gbertoli/hww/Diboson_v20_taus/tmp/Linux2.6-GCC_4_1/Ana/srt_dep_tmp.27294': No such file or directory
gmake[2]: *** [/misc/cdf/gbertoli/hww/Diboson_v20_taus/tmp/Linux2.6-GCC_4_1/Ana/libAna-shared/Functions.o] Error 1
gmake[1]: *** [src.lib] Error 2
gmake: *** [Ana.all] Error 2
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
drkg4b
  • 377
  • 3
  • 14

3 Answers3

3

First off, the only valid signature for remove_if takes a single function as the predicate argument:

jets_pt.erase(std::remove_if(jets_pt.begin(), jets_pt.end(), eta),
              jets_pt.end());

This means that eta must be a function returning bool and taking precisely one argument whose type is the value type of the container:

bool eta(const std::pair<string, double> & p)
{
   // do something useful with p
}

If this doesn't fit your bill because you need additional state information in the predicate, then you need to make it a function object:

struct Eta
{
  const std::map<string, TLorentzVector> & map_jets;
  Eta(const std::map<string, TLorentzVector> & m) : map_jets(m) { }
  bool operator()(const std::pair<string, double> & p) const
  {
    std::map<string, TLorentzVector>::const_iterator it = map_jets.find(p->second);
    return it == map_jets.end() ?
                 false          :
                 std::fabs(it->second.PseudoRapidity()) > 2.5;
  }
};

Now you have to use remove_if with an instance of Eta:

jets_pt.erase(std::remove_if(jets_pt.begin(), jets_pt.end(), Eta(map_jets)),
              jets_pt.end());  //                            ^^^^^^^^^^^^^

Note that your use of the for loop is extremely suspicious; you should double-check that.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Ok, I've undestood the point. I've added information on what I want to achieve, that is removing elements from a vector of pairs. – drkg4b Nov 24 '11 at 17:18
  • That's also what this answer does. Which point is unclear? (Edit:) The last line by itself already does what you want, I think. No loop, just one line. – Kerrek SB Nov 24 '11 at 17:20
  • Thanks for the answer, I'm not experienced in objects at all. Is there any other solution to look in my vector to find those elements which have the required condition to be removed from there? I've tried to use jets_pt.erase(it) but the problem is that the vector could also be 0 size and it can happen that the last element is erased this ends with an error. – drkg4b Nov 24 '11 at 17:37
  • The solution I posted is by far the easiest, most readable and most efficient one. It's not that bad, just stare at it for a bit and break it down into bits if you have trouble following it. Since you were the one who came up with the idea in the first place, I'm assuming that you sort of have a grasp on the bigger picture. – Kerrek SB Nov 24 '11 at 17:39
  • Apologies also for a mistake (now fixed): You need to pass the map reference to the predicate object. Also you can't use the square-brackets on a constant map, so I changed that to a `find()`. – Kerrek SB Nov 24 '11 at 17:41
  • Thanks! I try to learn something new from your answer. Do you think that I might have problems if I do something like for( vector >::iterator it = jets_pt.begin(); it != jets_pt.end(); ++it) if (fabs(map_jets[jet].PseudoRapidity()) > 2.5) jets_pt.erase(it--); – drkg4b Nov 24 '11 at 17:59
  • Don't do that. That hugely inefficient. That's exactly why the remove/erase idiom exists. – Kerrek SB Nov 24 '11 at 18:01
  • eheh ok, thanks, I'm just a physicist learning c++ to work. Thanks for the answer, there's a lot of new things for me to learn! – drkg4b Nov 24 '11 at 18:12
  • @drkg4b: Indeed! The standard library is a gold mine; do spend some time reading through its many gems. And don't hesitate to post questions on SO of course! :-) – Kerrek SB Nov 24 '11 at 18:16
0

std::remove_if takes a value of the contained type (bool pred (container::value_type), or a functor which overloads operator() appropriately).

For std::map, you have to do it like explained here remove_if equivalent for std::map .

Community
  • 1
  • 1
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
0

You're passing a bool (the results of calling eta) to remove_if as the third argument. You need to pass it a predicate: a pointer to a function taking a single argument and returning something which can be converted to a bool, or a functional object. In the error messages, __pred is your third argument; remove_if calls it here with a pair<string, double>, and expects a bool in return. You have to provide something which can be called like this. (You might want to look into boost::bind.)

And BTW: passing a map by value to eta might not be a good idea. It's going to slow things down considerably if the map is big.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Thanks, I'm not a good and experienced programmer, my map is only 7 elements long and it really simplify the selection of the things i want to use. – drkg4b Nov 24 '11 at 17:32