
namespace CGAL {

/// \addtogroup kernel_dimension

/// @{

/*!
The class `Ambient_dimension` allows to retrieve the dimension of the ambient space of
a type `T` in a kernel `K`.

\cgalHeading{Parameters}

The parameter `K` has the default value `Kernel_traits<T>::Kernel>`.

\cgalHeading{Example}

The following retrieves the dimension of a point type.

\code
typedef K::Point_2 Point;
int dimension = Ambient_dimension<Point, K>::value;
assert(dimension == 2);
\endcode

\sa `CGAL::Dimension_tag<int dim>`
\sa `CGAL::Dynamic_dimension_tag`
\sa `CGAL::Feature_dimension<T, K>`

*/
template< typename T, typename K = typename Kernel_traits<T>::Kernel >
struct Ambient_dimension {

/// \name Constants
/// @{

/*!
The dimension value as a compile-time
integral constant. It is implemented as `K::Ambient_dimension<T>::%type::%value`.
It exists only when the dimension is a compile-time constant.
*/
static const int value;

/// @}

/// \name Types
/// @{

/*!
Either `Dimension_tag<dim>` if the dimension is a
compile-time constant of value `dim`, or `Dynamic_dimension_tag`
otherwise. It is implemented as `K::Ambient_dimension<T>::%type`.
*/
typedef unspecified_type type;

/// @}

}; /* end Ambient_dimension */

/*!


An object of the class `Dimension_tag` is an empty object which can be used
for dispatching functions based on the dimension of an object, as provided
by the `dim` parameter. It is useful in cases where it is not more
practical to pass the dimension as a template parameter directly.

\cgalHeading{Example}

The following code declares two functions constructing two points at the origin,
either in 2D or in 3D.

\code
Point_2<K> get_origin(Dimension_tag<2>) { return Point_2<K>(ORIGIN); }
Point_3<K> get_origin(Dimension_tag<3>) { return Point_3<K>(ORIGIN); }

std::cout << get_origin(Dimension_tag<2>())) << std::endl;
\endcode

\sa `CGAL::Ambient_dimension<T, K>`
\sa `CGAL::Feature_dimension<T, K>`
\sa `CGAL::Dynamic_dimension_tag`

*/
template< typename int dim >
struct Dimension_tag {

/// \name Constants
/// @{

/*!
The value of the `dim` parameter.
*/
static const int value;

/// @}

}; /* end Dimension_tag */

/*!


An object of the class `Dynamic_dimension_tag` is an empty object which can be used
for dispatching functions based on the dimension of an object.
`Dynamic_dimension_tag` indicates that the dimension is not known at compile-time.
`Dimension_tag` is the tag class dealing with compile-time dimensions.

\cgalHeading{Example}

The following code declares two functions constructing two points at the origin,
either in 2D or in 3D.

\code
Point_2<K> get_origin(Dimension_tag<2>) { return Point_2<K>(ORIGIN); }
Point_3<K> get_origin(Dimension_tag<3>) { return Point_3<K>(ORIGIN); }
Point_d<K> get_origin(Dynamic_dimension_tag) { return Point_d<K>(ORIGIN); }

std::cout << get_origin(Dynamic_dimension_tag())) << std::endl;
\endcode

\sa `CGAL::Dimension_tag<int dim>`
\sa `CGAL::Ambient_dimension<T, K>`
\sa `CGAL::Feature_dimension<T, K>`

*/

struct Dynamic_dimension_tag {

}; /* end Dynamic_dimension_tag */

/*!

The class `Feature_dimension` allows to retrieve the geometric dimension of a type `T`
in a kernel `K`.

\cgalHeading{Parameters}

The parameter `K` has the default value `Kernel_traits<T>::Kernel`.

\cgalHeading{Example}

The following retrieves the dimension of a point type.

\code
typedef K::Point_2 Point;
int dimension = Feature_dimension<Point, K>::value;
assert(dimension == 0);
\endcode

\sa `CGAL::Dimension_tag<int dim>`
\sa `CGAL::Dynamic_dimension_tag`
\sa `CGAL::Ambient_dimension<T, K>`

*/
template< typename T, typename K = typename Kernel_traits<T>::Kernel >
struct Feature_dimension {

/// \name Constants
/// @{

/*!
The dimension value as a compile-time
integral constant. It is implemented as `K::Feature_dimension<T>::%type::%value`.
It exists only when the dimension is a compile-time constant.
*/
static const int value;

/// @}

/// \name Types
/// @{

/*!
Either `Dimension_tag<dim>` if the dimension is a
compile-time constant of value `dim`, or `Dynamic_dimension_tag`
otherwise. It is implemented as `K::Feature_dimension<T>::%type`.
*/
typedef unspecified_type type;

/// @}

}; /* end Feature_dimension */

/// @}

} /* end namespace CGAL */

