Terms 40: Make the imitation functionality
Suppose I have a Widget * pointer's list and a function to determine if such a pointer determines an interesting widget:
List
Bool isinteresting (Const Widget * Pw);
If I want to find the first pointer to interesting Widget in list: This is simple:
List
isinteresting;
IF (i! = widgetPTRS.End ()) {
... // Treat the first one
} // Interesting pointing
// Widget's pointer
But if I want to find the first pointer to the unresporated Widget, it is obvious that the method is compiled:
List
Find_if (WidgetPTRS.BEGIN (), widgetptrs.end (),
Not1 (isinteresting)); // Error! Cannot compile
Instead, I have to apply PTR_FUN to ISINTERESTISTING before applying NOT1:
List
Find_if (WidgetPTRS.BEGIN (), widgetptrs.end (),
Not1 (PTR_FUNC (ISINTERESTING)))))))))))); // No problem
IF (i! = widgetPTRS.End ()) {
... // Treat the first one
} // Pointer to widget
That will lead some questions. Why do I have to apply PTR_FUN to ISINTERESTING? PTR_FUN did what I did, how to finish the work above?
Some of the answers are amazing. The only thing PTR_FUN does make some typedef valid. That's it. NOT1 needs these typefef, which is why not1 can be applied to PTR_FUN, but not directly apply Not1. Because it is a low-level function pointer, IsInteresting lacks typedef required for Not1.
NOT1 is not the only component that requires those required by STL. All four standard function adapters (NOT1, NOT2, BIND1ST, and BIND2ND) require some typedef, some other person-written non-standard STL compatible adapters (such as from SGI and Boost-see Terms 50). The function object that provides these necessary typedef is called adaptable, and lack of the function objects of TypeDef are uncomfortable. Adapted to uncomfortable function objects can be used for more scenes, so as long as you can do you, you should make your function object adapt. This doesn't cost anything, and it can buy a convenient world for customers who are imitated.
I know I know. I am selling, often mentioning "some typefef" without telling you what. The typefef in the problem is argument_type, first_argument_type, second_argument_type and result_type, but not so straightforward, because different types of imitation functionals need to provide those names of different subsets. Overall, unless you are writing your own adapter (this book does not have the subject of the subject), you don't need to know anything about TypeDef. That is because the regular way to provide them is from a base class, or, more accurately, one base structure, inherit them. Operator () with a parameter of the imitation function class, the structure to be inherited is std :: unary_function. Operator () has two parameters of imitation function class, the structure to inherit is std :: binary_function. Ok, simply, unary_function and binary_function are templates, so you can't inherit them directly. Instead, you must inherit from the class they generated, and then you need some type of type parameters. For unary_function, you must specify the type of parameters that is taken by your oscillatic function class and its return type. For binary_function, you have to specify three types: your Operator's first and second parameters, and return your Operator.
Here are two examples:
Template
Class MeetSthreshold: Public Std :: unary_function
Private:
CONST T threshold;
PUBLIC:
Meetsthreshold (Const T & thReshold);
Bool Operator () (Const Widget &) Const;
...
}
Struct WidgetNameCompare:
Std :: binary_function
Bool Operator () (Const Widget & lh, Const Widget & rhs) Const;
}
In both cases, pay attention to the type of unary_function or binary_function and the Operator () passing to the imitation function class, the same, although the return type of the Operator is passed to Unary_Function or binary_function, there is a little quirky.
You may notice that MeetSthreshold is a class, and WidgetNameCompare is a structure. MeetSthresh has internal status (its threshold data member), and class is a reasonable method of encapsulating those information. WidgetNameCompare is not status, so there is no need for any private. Everything is the authors of public imitation functionals often declare them as struct rather than Class, perhaps only because you can avoid entering "public" in front of the base class and Operator () functions. Declaring such an imitation function as a Class or Struct is purely a personal style. If you are still refining your personal style, you want to find some imited objects, see where there is no state STL yourself, such as Less
Struct WidgetNameCompare:
Std :: binary_function
}
Although the parameter type of Operator is Const Widget &, it is transmitted to binary_function. In general, the non-pointer type transmitted to Unary_Function or Binary_Function has removed Const and reference. (Don't ask why. Reasons are not very good. If you really want to know, write some programs that don't get rid of them, then to dissect the compiler diagnosis results. If you have completed this, you still have interest to this issue Access Boost.org (see Terms 50) and then look at their work about characteristics and function object adapters.)
This rule changed when the parameter of the operator () is a pointer. There is a structure similar to WidgetNameCompare, but this uses widget * pointer:
Struct PtrwidgetNameCompare:
Std: binary_function
Bool Operator () (Const Widget * LHS, Const Widget "RHS) Const;
}
Here, pass the type of binary_function and the type of Operator (). A general rule for the imitation function for bringing or returning a pointer is to pass the type of unary_function or binary_function is the type of Operator () with or returned.
Don't forget all redundant texts that use these unary_function and binary_function base classes. These classes provide the typedef required for the function object adapter, so inheritably generates the adaptive function object from those class. That makes us do this:
List
...
List
Find_if (widgets.rbegin (), widgets.rend (), // suitable for threshold 10 Widget
NOT1 (MeetSthreshold
Widget W (constructor parameters);
List
Find_if (widgets.begin (), widgets.end (), // widgetnamecompare definition
Bind2nd (WidgetNameCompare (), W); //'s sort order Popular Widget
If we don't inherit the imitation function class from Unary_Function or Binary_Function, these examples cannot be compiled, because NOT1 and BIND2nd are only working with adaptive function objects.
The STL function object imitates the C function, and a C function has only one set of parameter types and a return type. As a result, STL secretly assumes that each imitation function class has only one Operator () function, and the parameters of this function should be passed to Unary_Function or Binary_Function (consistent with the references we just discussed and the rules of the pointer type). This means that although it may be very attractive, you can't create the functionality of the WidgetNameCompare and PtrwidgetNameCompare, which is unique to try to set up a separate structure of two Operator () functions. If you have done it, this imitation function may be able to adapt with up to one of its call form (you pass parameters to binary_function), and a method of improving only half adaptation can be better than it is better than it is. Sometimes it is necessary to give an example of multiple call forms (so gives up the adaptive), clauses 7, 20, 23, and 25. But that type of imitation function is exception, not rules. Adaptedness is important, every time you write the fixing function class, you should work hard to promote it.