Professional C__ - Marc Gregoire [231]
mem_fn(), mem_fun_ref(), and mem_fun()are not the most intuitive ways to implement the findEmptyString() function. Using C++11 lambda expressions, it can be implemented in a much more readable and elegant way. Here is the implementation using a lambda expression working on a container of objects:
void findEmptyString(const vector { auto end = strings.end(); auto it = find_if(strings.begin(), end, [](const string& str){ return str.empty(); }); // Remaining of function omitted because it is the same as earlier } Code snippet from FunctionObjects\EmptyString.cpp Similarly, the following uses a lambda expression working on a container of pointers to objects: void findEmptyString(const vector { auto end = strings.end(); auto it = find_if(strings.begin(), end, [](const string* str){ return str->empty(); }); // Remaining of function omitted because it is the same as earlier } Code snippet from FunctionObjects\EmptyStringPtr.cpp Both mem_fun_ref() and mem_fun() have been deprecated by C++11. Use lambda expressions instead, or mem_fn(). Adapting Real Functions You can’t use normal function pointers directly with the function adapters bind1st(), bind2nd(), not1(), or not2(), because these adapters require specific typedefs in the function objects they adapt. For example, not1() can only operate on function objects that include an argument_type typedef, while not2() requires a first_argument_type and second_argument_type typedef. The bind1st() and bind2nd() adapters require similar typedefs. One last function adapter provided by the C++ standard library, ptr_fun(), allows you to wrap regular function pointers in a way that they can be used with the adapters. The ptr_fun() adapter is only explained here because you might encounter it in older codebases. If you are writing new code and are using a C++11 compiler, you should use lambda expressions. As an example, suppose that you want to write a function isNumber() that returns true if every character in a string is a digit. The C++ string class provides an iterator. Thus, you can use the find_if() algorithm to search for the first nondigit in the string. If you find one, the string is not a number. The The definition of isdigit() in The problem is that you want to find the first character that is not a digit, which requires the not1() adapter. However, because isdigit() is a C function, not a function object, you need to use the ptr_fun() adapter to generate a function object that can be used with not1(). The code looks as follows: bool isNumber(const string& str) { auto end = str.end(); auto it = find_if(str.begin(), end, not1(ptr_fun(::isdigit))); return (it == end); } Code snippet from FunctionObjects\IsNumber.cpp Note the use of the :: scope resolution operator to specify that isdigit() should be found in the global scope. C++11 has deprecated ptr_fun() and you should use a lambda expression instead: bool isNumber(const string& str) { auto end = str.end(); auto it = find_if(str.begin(), end, [](char c){return !::isdigit(c);}); return (it == end); } Code snippet from FunctionObjects\IsNumber.cpp For this example, you can also use the new C++11 find_if_not() algorithm as follows: bool isNumber(const string& str) { auto end = str.end(); auto it = find_if_not(str.begin(), end, ::isdigit); return (it == end); } Code snippet from FunctionObjects\IsNumber.cpp ptr_fun() has been deprecated by C++11. Use lambda