12

I'm currently stuck finding the correct syntax for trimming each string in a std::vector.

I tried

std::vector<std::string> v;
std::for_each(v.begin(), v.end(), &boost::trim);

which gave me the following error messages in MSVC7.1.

error C2784: '_Fn1 std::for_each(_InIt,_InIt,_Fn1)' : could not deduce template argument for 'T1' from 'std::vector<_Ty>::iterator' with [_Ty=std::string] : see declaration of 'std::for_each'

error C2896: '_Fn1 std::for_each(_InIt,_InIt,_Fn1)' : cannot use function template 'void boost::algorithm::trim(SequenceT &,const std::locale &)' as a function argument : see declaration of 'boost::algorithm::trim'

If I explicitly give the template parameter trims second parameter can not be found by the compiler, though its set by default.

std::for_each(v.begin(), v.end(), &boost::trim<std::string>);

error C2198: 'void (__cdecl *)(std::string &,const std::locale &)' : too few arguments for call through pointer-to-function

I was wondering how the correct syntax to call trim for each element in v would look like.

Community
  • 1
  • 1
Norbert
  • 123
  • 1
  • 4
  • 2
    Note also that `for_each` is not used to modify original sequences. Use `transform` instead. – Diego Sevilla Feb 08 '10 at 13:37
  • 4
    Wrong, for_each is perfect for what he's doing. Keep in mind that boost::trim returns void, which means that it can't be used with transform. – Manuel Feb 08 '10 at 13:44
  • Isn't there a boost::trim_copy just for this situation? – Rob Feb 08 '10 at 13:55
  • 1
    Yes, except that there was no situation in the first place: the OP's use of for_each was fine. See this related thread: http://stackoverflow.com/questions/662845/why-is-stdfor-each-a-non-modifying-sequence-operation – Manuel Feb 08 '10 at 14:01
  • @Diego: Other way around. `transform` is intended to be immutable, which is why it takes a destination iterator. – jalf Feb 08 '10 at 15:44

1 Answers1

25

You need to bind as well the second parameter of trim (the locale):

std::vector<std::string> v;
std::for_each(v.begin(), v.end(), 
              boost::bind(&boost::trim<std::string>,
                          _1, std::locale() ));
Manuel
  • 12,749
  • 1
  • 27
  • 35
  • Thanks. I thought about bind too, but I didn't think I could easily add the second parameter there. You helped a lot. – Norbert Feb 08 '10 at 13:49