mirror of https://github.com/CGAL/cgal
175 lines
5.1 KiB
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}
|