CGateContainer

Name

CGateContainer -- Pointer like class for Gates.

Synopsis


#include <GateContainer.h>
class CGateContainer : public CNamedItem {
 public:

  CGateContainer() ;
  CGateContainer (const std::string& sName, UInt_t nNumber, 
		  CGate& rGate);  
  CGate* getGate() const;   
  void setGate (CGate* am_pGate);
  CGate& operator* () ;

  CGate* operator-> () ;
  Bool_t operator() (CEvent& rEvent);
};

        

DESCRIPTION

SpecTcl gates are mutable. Not only can the constituents be modified, but the gate type can also be changed. If objects depending on gates held a pointer or reference to that gate, SpecTcl would need to update all references to a gate whenever the gate was modified, a potentially costly and error prone process.

It would be possible for gate clients to have a pointer to a pointer. That would work. Changing a gate would change the underlying pointer and the pointer to that pointer could remain valid. That would lead to notational abominations like (*pGate)->operator().

Instead of this, SpecTcl employes a pointer like object called a gate container. The gate container contains a gate and wraps it with pointer like semantics. Gate containers are derived from CNamedItem so it is the container that holds the name of a gate, not the gate itself. Clients of the gate can hold either a reference to the gate container (if the gate they are clients of won't change names) or a pointer to the gate container if, like spectra, they can.

METHODS

CGateContainer();

Default constructors must be defined for objects that will be inserted into STL container classes (such as std::Map). The default constructor constructs a gate container that will segfault when attempts are made to access the underlying gate.

Once constructed, assignment can be used to give the container and id, name and gate.

CGateContainer (const std::string& sName, UInt_t nNumber, CGate& rGate);

Constructs with a gate; rGate, an id; nNumber and a gate instance rGate.

const CGate* getGate();

Returns a pointer to the gate that is encapsulated by the gate container. Normally you won't need to call this as you can manipulate the gate via the methods supplied by the container.

void setGate(CGate* am_pGate);

Used by SpecTcl to replace the gate in the container. Note that when a gate is constructed into a gate container, containers are assigned or this method is called, the pointer passed in is not stored. Instead a clone of the gate is made and that is what's stored in the container.

Note that destroying the container also implicitly destroys the cloned gate. All of this means it's perfectly safe to have code like:


{
    Float_t xcoords[4] = {0.0, 100.0, 100.0, 0.0};
    Float_t ycoords[4] = {0.0, 0.0, 100.100, 100.100};
    CContour square(1, 2, 4, xcoords, ycoords);
    CGateContainer gc = new CGateContainer("rectangle", 100, square);
    
    return gc;
}                     // square object was destroyed here but gc's clone lives.
                    
CGate& operator*();

Implements the first part of pointer semantics; plain dereference. This returns a reference to the encapsulated gate. This allows code like:


CGateContainer gc;
...                       // Gate/name etc. set here.
CGate& gate(*gc);
std::string t = gate.Type();
                    
CGate* operator->();

Returns a pointer to the gate. This implements the second part of pointer semantics, member dereference. The method allows operations like:


CGateContainer gc;
...                      // Gate name etc. set here.

std::string t = gc->Type();       // Fetch gate type.

                    
Bool_t operator()(CEvent& rEvent);

This is a convenience method that evaluates the underlying gate for the event rEvent. Since the gate is encapsulated as a pointer, the actual gate's operator() is invoked. This allows code like:


// Assume spec is a CSpectrum reference and rEvent a CEvent reference.

Bool_t gateMade = (*spec.getGate())(rEvent);          // Evaluate the gate