Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1497274
types.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
14 KB
Referenced Files
None
Subscribers
None
types.hpp
View Options
//===-- rosa/support/types.hpp ----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/types.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Implementation of some basic convenience types.
///
/// \note This implementation is partially based on the implementation of
/// corresponding parts of CAF.
///
//===----------------------------------------------------------------------===//
#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 \c void.
///
/// \c rosa::UnitType is analogous to \c void, but can be safely returned,
/// stored, etc. to enable higher-order abstraction without cluttering code with
/// exceptions for \c void (which can't be stored, for example).
struct
UnitType
{
/// Constructor, needs to do nothing.
constexpr
UnitType
()
noexcept
{}
/// Copy-constructor, needs to do nothing.
constexpr
UnitType
(
const
UnitType
&
)
noexcept
{}
};
/// Aliasing \c rosa::UnitType as \c rosa::unit_t.
using
unit_t
=
UnitType
;
/// The value of \c rosa::unit_t.
///
/// \note Since a value of \c rosa::UnitType has no state, all instances of
/// \c rosa::UnitType is equal and considered *the \c rosa::unit_t value*.
static
constexpr
unit_t
unit
=
unit_t
{};
// NOLINT
/// \name LiftVoid
/// \brief Lifts a type to avoid \c void.
///
/// A type \c T can be lifted as \code
/// typename LiftVoid<T>::Type
/// \endcode
/// The resulted type is \c rosa::unit_t if \c T is \c void, and \c T itself
/// otherwise.
///@{
/// Definition for the general case.
///
/// \tparam T type to lift
template
<
typename
T
>
struct
LiftVoid
{
using
Type
=
T
;
};
/// Specialization for \c void.
template
<>
struct
LiftVoid
<
void
>
{
using
Type
=
unit_t
;
};
///@}
/// \name UnliftVoid
/// \brief Unlifts a type already lifted by \c rosa::LiftVoid.
///
/// A type \c T can be unlifted as \code
/// typename UnliftVoid<T>::Type
/// \endcode
/// The resulted type is \c void if \c T is \c rosa::unit_t -- that is \c void
/// lifted by \c rosa::LiftVoid --, and \c T itself otherwise.
///
///@{
/// Definition for the general case.
///
/// \tparam T type to unlift
template
<
typename
T
>
struct
UnliftVoid
{
using
Type
=
T
;
};
/// Specialization for \c 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 \c rosa::Optional by assigning an instance of
/// \c rosa::NoneType to it.
struct
NoneType
{
/// Constructor, needs to do nothing.
constexpr
NoneType
(
void
)
{}
/// Evaluates the instance to \c bool.
///
/// A "nothing" is always evaluates to \c false.
constexpr
explicit
operator
bool
(
void
)
const
{
return
false
;
}
};
/// Aliasing type \c rosa::NoneType as \c rosa::none_t.
using
none_t
=
NoneType
;
/// The value of \c rosa::none_t.
///
/// \note Since a value of \c rosa::NoneType has no state, all instances of
/// \c rosa::NoneType is equal and considered *the \c rosa::none_t value*.
static
constexpr
none_t
none
=
none_t
{};
// NOLINT
/* ************************************************************************** *
* Optional *
* ************************************************************************** */
/// \defgroup Optional Specializations of rosa::Optional
///
/// \brief Represents an optional value.
///
/// \note This implementation is compatible with \c 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 \p 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 \p 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 \p this object.
~
Optional
(
void
)
{
destroy
();
}
/// Updates \p 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 \p 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 \p this object contains a value.
///
/// \return if \p this object contains a value
explicit
operator
bool
(
void
)
const
{
return
Valid
;
}
/// Checks whether \p this object does not contain a value.
///
/// \return if \p this object does not contain a value
bool
operator
!
(
void
)
const
{
return
!
Valid
;
}
/// Returns the value stored in \p this object.
///
/// \return reference of the stored value
///
/// \pre \p this object contains a value
T
&
operator
*
(
void
)
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return reference of the stored value
///
/// \pre \p this object contains a value
const
T
&
operator
*
(
void
)
const
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return pointer to the stored value
///
/// \pre \p this object contains a value
const
T
*
operator
->
(
void
)
const
{
ASSERT
(
Valid
);
return
&
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return pointer of the stored value
///
/// \pre \p this object contains a value
T
*
operator
->
(
void
)
{
ASSERT
(
Valid
);
return
&
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return reference of the stored value
///
/// \pre \p this object contains a value
T
&
value
(
void
)
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return reference of the stored value
///
/// \pre \p this object contains a value
const
T
&
value
(
void
)
const
{
ASSERT
(
Valid
);
return
Value
;
}
/// Returns the stored value or a default.
///
/// If \p 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 \p this object does not contain
/// a value
///
/// \return reference to either the stored value or \p DefaultValue if \p 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 \p this object by moving a value into it.
///
/// \tparam V type of \p X
///
/// \param X value to move
///
/// \pre \p 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 \p 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 \p 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 \p 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 \p this object contains a reference.
///
/// \return if \p this object contains a reference
explicit
operator
bool
(
void
)
const
{
return
Value
!=
nullptr
;
}
/// Checks whether \p this object does not contain a reference.
///
/// \return if \p this object does not contain a reference
bool
operator
!
(
void
)
const
{
return
!
Value
;
}
/// Returns the reference stored in \p this object.
///
/// \return the stored reference
///
/// \pre \p this object contains a reference
T
&
operator
*
(
void
)
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return the stored reference
///
/// \pre \p this object contains a reference
const
T
&
operator
*
(
void
)
const
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return the stored reference
///
/// \pre \p this object contains a reference
T
*
operator
->
(
void
)
{
ASSERT
(
Value
);
return
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return the stored reference
///
/// \pre \p this object contains a reference
const
T
*
operator
->
(
void
)
const
{
ASSERT
(
Value
);
return
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return the stored reference
///
/// \pre \p this object contains a reference
T
&
value
(
void
)
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the value stored in \p this object.
///
/// \return the stored reference
///
/// \pre \p this object contains a reference
const
T
&
value
(
void
)
const
{
ASSERT
(
Value
);
return
*
Value
;
}
/// Returns the stored reference or a default.
///
/// If \p 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 \p this object does not contain
/// a reference
///
/// \return either the stored reference or \p DefaultValue if \p 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 \c void.
///
/// The specialization allows \c rosa::Optional to implement a flag for \c void.
template
<>
class
Optional
<
void
>
{
public
:
using
Type
=
unit_t
;
/// Creates an instance with a \c false flag.
///
/// \note Use it with its default parameter.
Optional
(
none_t
=
none
)
:
Value
(
false
)
{}
/// Creates an instance with a \c true flag.
///
/// \note The only argument is ignored because it can be *the \c 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 \p 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 \p this object contains a \p true flag.
///
/// \return if \p this object contains a \p true flag.
explicit
operator
bool
(
void
)
const
{
return
Value
;
}
/// Checks whether \p this object contains a \p false flag.
///
/// \return if \p this object contains a \p false flag.
bool
operator
!
(
void
)
const
{
return
!
Value
;
}
private
:
/// The stored flag.
bool
Value
;
};
///@}
}
// End namespace rosa
namespace
std
{
/// Returns the textual representation of any value of \c rosa::unit_t.
///
/// \return textual representation of \c rosa::UnitType.
inline
std
::
string
to_string
(
const
rosa
::
unit_t
&
)
{
return
"unit"
;
}
/// Dumps a \c rosa::Unit to a given \c std::ostream.
///
/// \param [in,out] OS output stream to dump to
/// \param U \c rosa::Unit to dump
///
/// \return \p OS after dumping \p U to it
inline
ostream
&
operator
<<
(
ostream
&
OS
,
const
rosa
::
unit_t
&
U
)
{
OS
<<
to_string
(
U
);
return
OS
;
}
/// Returns the textual representation of any value of \c rosa::none_t.
///
/// \return textual representation of \c rosa::NoneType.
inline
std
::
string
to_string
(
const
rosa
::
none_t
&
)
{
return
"none"
;
}
/// Dumps a \c rosa::none_t to a given \c std::ostream.
///
/// \param [in,out] OS output stream to dump to
/// \param N \c rosa::none_t to dump
///
/// \return \p OS after dumping \p N to it
inline
ostream
&
operator
<<
(
ostream
&
OS
,
const
rosa
::
none_t
&
N
)
{
OS
<<
to_string
(
N
);
return
OS
;
}
}
// End namespace std
#endif
// ROSA_SUPPORT_TYPES_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Mar 1, 9:31 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
286297
Default Alt Text
types.hpp (14 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment