Std :: for_each ignoring default function argument

I came across a strange compilation problem. I want to process a list of strings using std::for_each . The following simplified code illustrates the problem:

 # include <list> # include <string> # include <algorithm> using namespace std ; void f(wstring & str) { // process str here } void g(wstring & str, int dummy = 0) { // process str here, same as f, just added a second default dummy argument } int main(int, char*[]) { list<wstring> text ; text.push_back(L"foo") ; text.push_back(L"bar") ; for_each(text.begin(), text.end(), f) ; // OK, fine :) for_each(text.begin(), text.end(), g) ; // Compilation error, complains about // g taking 2 arguments, but called within std::for_each // with only one argument. // ... return 0 ; } 

I tested using MinGW 4.5.2 and MSVC10, both reported the same error message. Initially, I wanted to use boost::algorithm::trim as the processing function passed to std::for_each , but I found that it takes two arguments, the first of which is required (the string to process), and the second is optional (the locale providing definition for spaces).

Is there a way to keep clean when using std::for_each (and other standard algorithms) with functions or methods with default arguments? I found a way to make it work, but it is no more understandable and understandable, so the for loop starts to seem easier ...

 # include <list> # include <string> # include <algorithm> # include <boost/bind.hpp> # include <boost/algorithm/string.hpp> using namespace std ; using namespace boost ; // ... somewhere inside main list<wstring> text ; for_each(text.begin(), text.end(), bind(algorithm::trim<wstring>, _1, locale()) ; // One must deal with default arguments ... // for_each(text.begin(), text.end(), algorithm::trim<wstring>) would be a real pleasure 

Thanks for any help!

Note. I just started to learn English, sorry for the mistakes :)

+7
source share
1 answer

The default arguments are just a code generation tool, not part of the function signature, so you cannot get around this. You can wrap your function in a function object, but exactly what bind already does for you.

However, in C ++ 0x, you can conveniently save the result (and use std::bind ) to make the code more readable:

 auto trimmer = std::bind(boost::algorithm::trim<std::wstring>, std::placeholders::_1, std::locale()); std::for_each(text.begin(), text.end(), trimmer); 

(The reason you don't want to do this in C ++ 98/03 is because the return type of bind is something rather unsightly, and you won’t borrow anyone by writing it.)

Alternatively, again in C ++ 0x you can use lambda:

 std::for_each(text.begin(), text.end(), [](std::wstring & s){ boost::algorithm::trim<std::wstring>(s); }); 
+6
source

All Articles