Implementation classes and handles

A handle class contains an object that is a pointer to an instance of the corresponding implementation class.

For a predefined CP Optimizer class, IlcConstraintI, implementing an object with its own data members and virtual functions, CP Optimizer defines the handle class IlcConstraint. Essentially, such a handle class contains objects that are simply pointers to instances of the corresponding implementation class IlcConstraintI. When you extend CP Optimizer by defining a new implementation class, you must also define a function that returns a handle.

This rule applies particularly to the definition of new classes of constraints. Handles for constraints are instances of the class IlcConstraint. This class provides an instance of an implementation class, or more precisely, IlcConstraintI*. You must define a function that returns a handle, and the minimal service that the handle provides is to manage the memory allocation of instances in your implementation class. The form that it generally takes looks like this:


IlcConstraint MyConstraint( /* arguments for the constraint */){
        // get the optimizer from a variable
        return new (cp.getHeap()) MyConstraintI(cp, /* ...args... */);
}

The body of that function builds an instance of MyConstraintI by calling the constructor and allocates a place on the CP Optimizer heap by calling the overloaded operator, new (cp.getHeap() ... ). When you use this CP Optimizer new, you get an efficient allocator that automatically manages how memory is recovered in case of backtracking.

In the example, x != y, you write a function DiffConstraint which creates the constraint. Here's the code for it:


IlcConstraint DiffConstraint(IlcIntExp x, IlcIntExp y){
    IlcCPEngine cp = x.getCPEngine();
    return new (cp.getHeap()) DiffConstraintI(cp, x, y);
}

That definition, of course, has two parts: the implementation and the handle. To use this new constraint within the search, you simply write:


   cp.add(DiffConstraint(x, y));

This statement informs CP Optimizer to take the constraint into account within such mechanisms as propagation, backtracking and so forth. In general, it can be said that a call to DiffConstraint as written builds an instance of DiffConstraintI and returns a handle for that object (in other words, an encapsulation of the object) to post by means of the post member function. The instance of the implementation class is connected to the value events of the two decision variables. Every time these variables are fixed, the propagate member function is executed.