cgal/STL_Extension/doc_tex/STL_Extension_ref/Object.tex

175 lines
5.1 KiB
TeX

\begin{ccRefClass}{Object}
\ccInclude{CGAL/Object.h}
\ccDefinition
Some functions can return different types of objects. A typical
\CC\ solution to this problem is to derive all possible return
types from a common base class, to return a pointer to this
class and to perform a dynamic cast on this pointer. The class
\ccRefName\ provides an abstraction.
An object \ccStyle{obj} of the class \ccRefName\ can
represent an arbitrary class. The only operations it provides is
to make copies and assignments, so that you can put them in lists
or arrays. Note that \ccRefName\ is NOT a common base class for the
elementary classes. Therefore, there is no
automatic conversion from these classes to \ccRefName. Rather
this is done with the global function \ccc{make_object}. This
encapsulation mechanism requires the use of \ccc{assign} or
\ccc{object_cast} to use the functionality of the encapsulated class.
This class is similar in spirit to \ccc{boost::any}.
\ccCreation
\ccCreationVariable{obj}
\ccConstructor{Object();}
{introduces an empty object.}
\ccConstructor{Object(const Object &o);}
{Copy constructor.}
Objects of type \ccRefName\ are normally created using the global function
\ccc{make_object}.
\ccOperations
\ccMethod{Object &operator=(const Object &o);}
{Assignment.}
\ccMethod{bool empty();}{returns true, if \ccVar\ does not
contain an object.}
\ccMethod{template<class T> bool is();}
{returns true, iff \ccVar\ contains an object of type \ccc{T}.}
\ccMethod{const std::type_info & type() const;}
{returns the type information of the contained type,
or \ccc{typeid(void)} if empty.}
Construction of an \ccc{Object} storing an object of type \ccc{T}
can be performed using the \ccc{make_object} global function :
\ccFunctionTemplate{T}{template <class T> Object make_object(const T &t);}
{Creates an object that contains \ccStyle{t}.}
Assignment of an object of type \ccRefName\ to an object of type \ccc{T}
can be done using \ccc{assign} :
\ccFunctionTemplate{T}{template <class T> bool assign(T& c, const Object& o);}
{assigns \ccStyle{o} to \ccStyle{c} if \ccStyle{o}
was constructed from an object of type \ccStyle{T}.
Returns \ccc{true}, if the assignment was possible.
For efficiency reasons, we recommend using \ccc{object_cast} instead.}
Another possibility to access the encapsulated object is to use \ccc{object_cast},
which avoids the default constructor and assignment required by \ccc{assign} :
\ccFunctionTemplate{T}{template <class T> const T * object_cast(const Object * o);}
{Returns a pointer to the object of type \ccc{T} stored by \ccc{o},
if any, otherwise returns \ccc{NULL}.}
\ccFunctionTemplate{T}{template <class T> T object_cast(const Object & o);}
{Returns a copy of the object of type \ccc{T} stored by \ccc{o},
if any, otherwise throws an exception of type \ccc{Bad_object_cast}.}
\ccExample
In the following example, the object class is used as return value for the
\ccHtmlNoLinksFrom{intersection} computation, as there are possibly different return values.
\begin{cprog}
{
typedef Cartesian<double> K;
typedef K::Point_2 Point_2;
typedef K::Segment_2 Segment_2;
Point_2 point;
Segment_2 segment, segment_1, segment_2;
std::cin >> segment_1 >> segment_2;
Object obj = intersection(segment_1, segment_2);
if (assign(point, obj)) {
/* do something with point */
} else if (assign(segment, obj)) {
/* do something with segment*/
}
\end{cprog}
\ccHtmlLinksOff%
\begin{cprog}
/* there was no intersection */
}
\end{cprog}
\ccHtmlLinksOn%
\medskip
A more efficient way to access the object is to use \ccc{object_cast},
which allows to skip a default construction and assignment :
\begin{cprog}
{
typedef Cartesian<double> K;
typedef K::Point_2 Point_2;
typedef K::Segment_2 Segment_2;
Segment_2 segment_1, segment_2;
std::cin >> segment_1 >> segment_2;
Object obj = intersection(segment_1, segment_2);
if (const Point_2 * point = object_cast<Point_2>(&obj)) {
/* do something with *point */
} else if (const Segment_2 * segment = object_cast<Segment_2>(&obj)) {
/* do something with *segment*/
}
\end{cprog}
\ccHtmlLinksOff%
\begin{cprog}
/* there was no intersection */
}
\end{cprog}
\ccHtmlLinksOn%
\medskip
The \ccHtmlNoLinksFrom{intersection} routine itself looks roughly as follows:
\begin{cprog}
template < class Kernel >
Object intersection(Segment_2<Kernel> s1, Segment_2<Kernel> s2)
{
\end{cprog}
\ccHtmlLinksOff%
\begin{cprog}
if (/* intersection is a point */ ) {
\end{cprog}
\ccHtmlLinksOn%
\begin{cprog}
Point_2<Kernel> p = ... ;
return make_object(p);
\end{cprog}
\ccHtmlLinksOff%
\begin{cprog}
} else if (/* intersection is a segment */ ) {
\end{cprog}
\ccHtmlLinksOn%
\begin{cprog}
Segment_2<Kernel> s = ... ;
return make_object(s);
}
\end{cprog}
\ccHtmlLinksOff%
\begin{cprog}
/* empty intersection */
return Object();
}
\end{cprog}
\end{ccRefClass}