Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F25859968
types.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
13 KB
Referenced Files
None
Subscribers
None
types.hpp
View Options
/***************************************************************************//**
*
* \file rosa/support/types.hpp
*
* \author David Juhasz (david.juhasz@tuwien.ac.at)
*
* \date 2017
*
* \brief Implementation of some basic convenience types.
*
* \note This implementation is partially based on the implementation of
* corresponding parts of CAF.
* \todo Check license.
*
******************************************************************************/
#ifndef ROSA_SUPPORT_TYPES_HPP
#define ROSA_SUPPORT_TYPES_HPP
#include
"rosa/support/debug.hpp"
#include
<string>
namespace
rosa
{
/* ************************************************************************** *
* Unit *
* ************************************************************************** */
/// A safe type to replace `void`.
///
/// `rosa::UnitType` is analogous to `void`, but can be safely returned, stored,
/// etc. to enable higher-order abstraction without cluttering code with
/// exceptions for `void` (which can't be stored, for example).
struct
UnitType
{
/// Ctor, needs to do nothing.
constexpr
UnitType
()
noexcept
{}
/// Copy-ctor, needs to do nothing.
constexpr
UnitType
(
const
UnitType
&
)
noexcept
{}
};
/// Aliasing `rosa::UnitType` as `rosa::unit_t`.
using
unit_t
=
UnitType
;
/// The value of `rosa::unit_t`.
///
/// \note Since a value of `rosa::UnitType` has no state, all instances of
/// `rosa::UnitType` is equal and considered *the `rosa::unit_t` value*.
static
constexpr
unit_t
unit
=
unit_t
{};
// NOLINT
/// Returns the textual representation of any value of `rosa::unit_t`.
///
/// \return textual representation of `rosa::UnitType`.
inline
std
::
string
to_string
(
const
unit_t
&
)
{
return
"unit"
;
}
/// \name LiftVoid
/// \brief Lifts a type to avoid `void`.
///
/// A type `T` can be lifted as \code
/// typename LiftVoid<T>::Type
/// \endcode
/// The resulted type is `rosa::unit_t` if `T` is `void`, and `T` itself
/// otherwise.
///@{
/// Definition for the general case.
///
/// \tparam T type to lift
template
<
typename
T
>
struct
LiftVoid
{
using
Type
=
T
;
};
/// Specialization for the type `void`.
template
<>
struct
LiftVoid
<
void
>
{
using
Type
=
unit_t
;
};
///@}
/// \name UnliftVoid
/// \brief Unlifts a type already lifted by `rosa::LiftVoid`.
///
/// A type `T` can be unlifted as \code
/// typename UnliftVoid<T>::Type
/// \endcode
/// The resulted type is `void` if T is `rosa::unit_t` -- that is `void` lifted
/// by `rosa::LiftVoid --, and `T` itself otherwise.
///
///@{
/// Definition for the general case.
///
/// \tparam T type to unlift
template
<
typename
T
>
struct
UnliftVoid
{
using
Type
=
T
;
};
/// Specialization for the type `rosa::unit_t`.
template
<>
struct
UnliftVoid
<
unit_t
>
{
using
Type
=
void
;
};
///@}
/* ************************************************************************** *
* None *
* ************************************************************************** */
/// Represents *nothing*.
///
/// An instance of the type represents *nothing*, that can be used, e.g., for
/// clearing an instance of `rosa::Optional` by assigning an instance of
/// `rosa::NoneType` to it.
struct
NoneType
{
/// Ctor, needs to do nothing.
constexpr
NoneType
(
void
)
{}
/// Evaluates the instance to `bool`.
///
/// A "nothing" is always evaluates to `false`.
constexpr
explicit
operator
bool
(
void
)
const
{
return
false
;
}
};
/// Aliasing type `rosa::NoneType` as `rosa::none_t`.
using
none_t
=
NoneType
;
/// The value of `rosa::none_t`.
///
/// \note Since a value of `rosa::NoneType` has no state, all instances of
/// `rosa::NoneType` is equal and considered *the `rosa::none_t` value*.
static
constexpr
none_t
none
=
none_t
{};
// NOLINT
/// Returns the textual representation of any value of `rosa::none_t`.
///
/// \return textual representation of `rosa::NoneType`.
inline
std
::
string
to_string
(
const
none_t
&
)
{
return
"none"
;
}
/* ************************************************************************** *
* Optional *
* ************************************************************************** */
/// \defgroup Optional
/// \brief Represents an optional value.
///
/// \note This implementation is compatible with `std::optional` of C++17.
///@{
/// Definition for the general case, optionally storing a value.
///
/// \tparam T type of the optional value
template
<
class
T
>
class
Optional
{
public
:
using
Type
=
T
;
/// Creates an instance without value.
///
/// \note Use it with its default parameter.
Optional
(
const
none_t
&
=
none
)
:
Valid
(
false
)
{}
/// Creates a valid instance with value.
///
/// \tparam U type of the `X`
/// \tparam E always use it with default value!
///
/// \param X value to store in the object
///
/// \note The constructor is available for types that are convertible to `T`.
template
<
class
U
,
class
E
=
typename
std
::
enable_if
<
std
::
is_convertible
<
U
,
T
>::
value
>::
type
>
Optional
(
U
X
)
:
Valid
(
false
)
{
cr
(
std
::
move
(
X
));
}
/// Creates an instance as a copy of another one.
///
/// \param Other the instance whose state to copy
Optional
(
const
Optional
&
Other
)
:
Valid
(
false
)
{
if
(
Other
.
Valid
)
{
cr
(
Other
.
Value
);
}
}
/// Creates an instance by moving the state of another one.
///
/// \param Other the instance whose state to obtain
Optional
(
Optional
&&
Other
)
noexcept
(
std
::
is_nothrow_move_constructible
<
T
>::
value
)
:
Valid
(
false
)
{
if
(
Other
.
Valid
)
{
cr
(
std
::
move
(
Other
.
Value
));
}
}
/// Destroys the instance.
~
Optional
(
void
)
{
destroy
();
}
/// Updates `this` object by copying the state of another one.
///
/// \param Other the instance whose state to copy
///
/// \return reference of the updated instance
Optional
&
operator
=
(
const
Optional
&
Other
)
{
if
(
Valid
)
{
if
(
Other
.
Valid
)
{
Value
=
Other
.
Value
;
}
else
{
destroy
();
}
}
else
if
(
Other
.
Valid
)
{
cr
(
Other
.
Value
);
}
return
*
this
;
}
/// Updates `this` object by moving the state of another one.
///
/// \param Other the instance whose state to obtain
///
/// \return reference of the updated instance
Optional
&
operator
=
(
Optional
&&
Other
)
noexcept
(
std
::
is_nothrow_destructible
<
T
>::
value
&&
std
::
is_nothrow_move_assignable
<
T
>::
value
)
{
if
(
Valid
)
{
if
(
Other
.
Valid
)
{
Value
=
std
::
move
(
Other
.
Value
);
}
else
{
destroy
();
}
}
else
if
(
Other
.
Valid
)
{
cr
(
std
::
move
(
Other
.
Value
));
}
return
*
this
;
}
/// Checks whether `this` object contains a value.
///
/// \return if `this` object contains a value
explicit
operator
bool
(
void
)
const
{
return
Valid
;
}
/// Checks whether `this` object does not contain a value.
///
/// \return if `this` object does not contain a value
bool
operator
!
(
void
)
const
{
return
!
Valid
;
}
/// Returns the value stored in `this` object.
///
/// \return reference of the stored value
///
/// \pre `this` object contains a value
T
&
operator
*
(
void
)
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return reference of the stored value
///
/// \pre `this` object contains a value
const
T
&
operator
*
(
void
)
const
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return pointer to the stored value
///
/// \pre `this` object contains a value
const
T
*
operator
->
(
void
)
const
{
ASSERT
(
Valid
);
return
&
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return pointer of the stored value
///
/// \pre `this` object contains a value
T
*
operator
->
(
void
)
{
ASSERT
(
Valid
);
return
&
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return reference of the stored value
///
/// \pre `this` object contains a value
T
&
value
(
void
)
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return reference of the stored value
///
/// \pre `this` object contains a value
const
T
&
value
(
void
)
const
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the stored value or a default.
///
/// If `this` object contains a value, then the stored value is returned. A
/// given default value is returned otherwise.
///
/// \param DefaultValue the value to return if `this` object does not contain
/// a value
///
/// \return reference to either the stored value or `DefaultValue` if `this`
/// object does not contain a value
const
T
&
valueOr
(
const
T
&
DefaultValue
)
const
{
return
Valid
?
Value
()
:
DefaultValue
;
}
private
:
/// Deallocates the stored value if any.
void
destroy
(
void
)
{
if
(
Valid
)
{
Value
.
~
T
();
Valid
=
false
;
}
}
/// Updates the state of `this` object by moving a value into it.
///
/// \tparam V type of `X`
///
/// \param X value to move into
///
/// \pre `this` object does not contain a value
template
<
class
V
>
void
cr
(
V
&&
X
)
{
ASSERT
(
!
Valid
);
Valid
=
true
;
new
(
&
Value
)
T
(
std
::
forward
<
V
>
(
X
));
}
/// Denotes if `this` object contains a value.
bool
Valid
;
/// Holds the stored value if any.
union
{
T
Value
;
///< The stored value.
};
};
/// Specialization storing a reference.
///
/// The specialization allows `rosa::Optional` to hold a reference
/// rather than an actual value with minimal overhead.
///
/// \tparam T the base type whose reference is to be stored
template
<
typename
T
>
class
Optional
<
T
&>
{
public
:
using
Type
=
T
;
/// Creates an instance without reference
///
/// \note Use it with its default parameter.
Optional
(
const
none_t
&
=
none
)
:
Value
(
nullptr
)
{}
/// Creates a valid instance with reference.
///
/// \param X reference to store in the object
Optional
(
T
&
X
)
:
Value
(
&
X
)
{}
/// Creates a valid instance with reference.
///
/// \param X pointer to store in the object as reference
Optional
(
T
*
X
)
:
Value
(
X
)
{}
/// Creates an instance as a copy of another one.
///
/// \param Other the instance whose state to copy
Optional
(
const
Optional
&
Other
)
=
default
;
/// Updates `this` object by copying the state of another one.
///
/// \param Other the instance whose state to copy
///
/// \return reference of the updated instance
Optional
&
operator
=
(
const
Optional
&
Other
)
=
default
;
/// Checks whether `this` object contains a reference.
///
/// \return if `this` object contains a reference
explicit
operator
bool
(
void
)
const
{
return
Value
!=
nullptr
;
}
/// Checks whether `this` object does not contain a reference.
///
/// \return if `this` object does not contain a reference
bool
operator
!
(
void
)
const
{
return
!
Value
;
}
/// Returns the reference stored in `this` object.
///
/// \return the stored reference
///
/// \pre `this` object contains a reference
T
&
operator
*
(
void
)
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return the stored reference
///
/// \pre `this` object contains a reference
const
T
&
operator
*
(
void
)
const
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return the stored reference
///
/// \pre `this` object contains a reference
T
*
operator
->
(
void
)
{
ASSERT
(
Value
);
return
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return the stored reference
///
/// \pre `this` object contains a reference
const
T
*
operator
->
(
void
)
const
{
ASSERT
(
Value
);
return
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return the stored reference
///
/// \pre `this` object contains a reference
T
&
value
(
void
)
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the value stored in `this` object.
///
/// \return the stored reference
///
/// \pre `this` object contains a reference
const
T
&
value
(
void
)
const
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the stored reference or a default.
///
/// If `this` object contains a reference, then the stored reference is
/// returned. A given default value is returned otherwise.
///
/// \param DefaultValue the value to return if `this` object does not contain
/// a reference
///
/// \return either the stored reference or `DefaultValue` if `this`object does
/// not contain a reference
const
T
&
valueOr
(
const
T
&
DefaultValue
)
const
{
return
Value
?
Value
()
:
DefaultValue
;
}
private
:
/// The stored reference as a pointer.
T
*
Value
;
};
/// Specialization storing `void`.
///
/// The specialization allows `rosa::Optional` to implement a flag for `void`.
template
<>
class
Optional
<
void
>
{
public
:
using
Type
=
unit_t
;
/// Creates an instance with a `false` flag.
///
/// \note Use it with its default parameter.
Optional
(
none_t
=
none
)
:
Value
(
false
)
{}
/// Creates an instance with a `true` flag.
///
/// \note The only argument is ignored because it can be *the `rosa::unit_t`
/// value* only.
Optional
(
unit_t
)
:
Value
(
true
)
{}
/// Creates an instance as a copy of another one.
///
/// \param Other the instance whose state to copy
Optional
(
const
Optional
&
Other
)
=
default
;
/// Updates `this` object by copying the state of another one.
///
/// \param Other the instance whose state to copy
///
/// \return reference of the updated instance
Optional
&
operator
=
(
const
Optional
&
Other
)
=
default
;
/// Checks whether `this` object contains a `true` flag.
///
/// \return if `this` object contains a `true` flag.
explicit
operator
bool
(
void
)
const
{
return
Value
;
}
/// Checks whether `this` object contains a `false` flag.
///
/// \return if `this` object contains a `false` flag.
bool
operator
!
(
void
)
const
{
return
!
Value
;
}
private
:
/// The stored flag.
bool
Value
;
};
///@}
}
// End namespace rosa
#endif
// ROSA_SUPPORT_TYPES_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Aug 29, 4:33 PM (21 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
328107
Default Alt Text
types.hpp (13 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment