diff --git a/include/rosa/deluxe/DeluxeTuple.hpp b/include/rosa/deluxe/DeluxeTuple.hpp index 9e26950..743872d 100644 --- a/include/rosa/deluxe/DeluxeTuple.hpp +++ b/include/rosa/deluxe/DeluxeTuple.hpp @@ -1,465 +1,465 @@ //===-- rosa/deluxe/DeluxeTuple.hpp -----------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/deluxe/DeluxeTuple.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2019 /// /// \brief Facilities for handling multiple input/output values for connections /// in the *deluxe interface*. /// /// \see \c rosa::deluxe::DeluxeContext /// //===----------------------------------------------------------------------===// #ifndef ROSA_DELUXE_DELUXETUPLE_HPP #define ROSA_DELUXE_DELUXETUPLE_HPP #include "rosa/support/sequence.hpp" #include "rosa/support/type_token.hpp" #include #include namespace rosa { namespace deluxe { /// A tuple to manage multiple input/output values in the *deluxe interface*. /// /// \tparam Ts types of elements of the tuple /// /// \note The template may be instantiated only with built-in types and the /// number of those type may not exceed the capacity of a \c rosa::Token. template struct DeluxeTuple : public std::tuple { // Statically enforce that the class template is instantiated only with // built-in types. STATIC_ASSERT((TypeListSubsetOf, BuiltinTypes>::Value), "not built-in types"); // Statically enforce that the class template is instantiated with not too // many types. // \note Instantiation would fail on \c rosa::deluxe::DeluxeTuple::TT if there - // are too any types; this assertion is for more readable error reporting. + // are too many types; this assertion is for more readable error reporting. STATIC_ASSERT(sizeof...(Ts) <= token::MaxTokenizableListSize, "Too many types"); /// How many elements the instance has. static constexpr token_size_t Length = sizeof...(Ts); /// What types the class contains. /// /// Type information encoded as \c rosa::Token. static constexpr Token TT = TypeToken::Value; /// Default constructor, zero-initializes elements. DeluxeTuple(void) = default; /// Constructor, initializes the underlying \c std::tuple with lvalue /// references. /// /// \param Args value references to the values to store DeluxeTuple(const std::decay_t &... Args) : std::tuple(Args...) {} /// Constructor, initializes the underlying \c std::tuple with rvalue /// references. /// /// \param Args rvalue references to the values to store DeluxeTuple(std::decay_t &&... Args) : std::tuple(std::move(Args)...) {} /// Contructor, initializes the underlying \c std::tuple from another matching /// \c std::tuple. DeluxeTuple(const std::tuple &Args) : std::tuple(Args) {} /// Default copy-constructor. DeluxeTuple(const DeluxeTuple &) = default; /// Default move-constructor. DeluxeTuple(DeluxeTuple &&) = default; /// Default copy-assignment. DeluxeTuple &operator=(const DeluxeTuple &) = default; /// Default move-assignment. DeluxeTuple &operator=(DeluxeTuple &&) = default; private: /// Dumps \p this object to a given \c std::ostream. /// /// \note Provides implementation for \c rosa::deluxe::DeluxeTuple::dump. /// /// \tparam S0 Indices for accessing elements. /// /// \param [in,out] OS output stream to dump to /// /// \note The second argument provides indices statically as template /// arguments \p S0..., so its actual value is ignored. /// /// \pre Statically, \p S0... matches number of types \p this object was /// created: \code /// sizeof...(S0) == sizeof...(Ts) /// \endcode template void dump(std::ostream &OS, Seq) const noexcept; public: /// Dumps \p this object to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to void dump(std::ostream &OS) const noexcept; }; template template void DeluxeTuple::dump(std::ostream &OS, Seq) const noexcept { STATIC_ASSERT(sizeof...(S0) == sizeof...(Ts), "inconsistent type arguments"); // Convert value to std::string with std::to_string except for a value of // std::string that does not need conversion. auto dump_to_string = [](const auto &V) { if constexpr (std::is_same, std::string>::value) { return V; } else { return std::to_string(V); } }; OS << "{"; (OS << ... << (" " + dump_to_string(std::get(*this)))); OS << " }"; } template void DeluxeTuple::dump(std::ostream &OS) const noexcept { dump(OS, seq_t()); } /// Type alias for a \c rosa::deluxe::DeluxeTuple that contains no elements. using EmptyDeluxeTuple = DeluxeTuple<>; /// Template specialization for \c rosa::deluxe::EmptyDeluxeTuple. template <> struct DeluxeTuple<> : public std::tuple<> { /// How many elements the instance has. static constexpr token_size_t Length = 0; /// What types the class contains. /// /// Type information encoded as \c rosa::Token. static constexpr Token TT = TypeToken<>::Value; /// Constructor, initializes the underlying \c std::tuple. DeluxeTuple(void) : std::tuple<>() {} /// Default copy-constructor. DeluxeTuple(const DeluxeTuple &) = default; // Default move-constructor. DeluxeTuple(DeluxeTuple &&) = default; /// Default copy-assignment. DeluxeTuple &operator=(const DeluxeTuple &) = default; // Default move-assignment, DeluxeTuple &operator=(DeluxeTuple &&) = default; /// Dumps \p this object to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to static void dump(std::ostream &OS) noexcept; }; /// Creates a \c rosa::deluxe::DeluxeTuple instance from the given lvalues /// references. /// /// \tparam Ts types of elements of the tuple /// /// \see \c rosa::deluxe::DeluxeTuple /// /// \param Args values to store in the tuple /// /// \return an instance of \c rosa::deluxe::DeluxeTuple with \p Args as /// elements template inline DeluxeTuple make_deluxe_tuple(const Ts &... Args) noexcept { return DeluxeTuple(Args...); } /// Creates a \c rosa::deluxe::DeluxeTuple instance from the given rvalue /// references. /// /// \tparam Ts types of elements of the tuple /// /// \see \c rosa::deluxe::DeluxeTuple /// /// \param Args values to store in the tuple /// /// \return an instance of \c rosa::deluxe::DeluxeTuple with \p Args as /// elements template inline DeluxeTuple make_deluxe_tuple(Ts&&... Args) noexcept { return DeluxeTuple(std::move(Args)...); } /// Creates a \c rosa::deluxe::DeluxeTuple instance from the given \c std::tuple /// reference. /// /// \tparam Ts types of elements of the tuple /// /// \see \c rosa::deluxe::DeluxeTuple /// /// \param Args values to store in the tuple /// /// \return an instance of \c rosa::deluxe::DeluxeTuple with \p Args as /// elements template inline DeluxeTuple make_deluxe_tuple(const std::tuple &Args) noexcept { return DeluxeTuple(Args); } /// \defgroup UnwrapDeluxeTuple Implementation of /// rosa::deluxe::UnwrapDeluxeTuple /// /// \brief Unwraps element types from an instance of \c /// rosa::deluxe::DeluxeTuple into a \c rosa::TypeList /// /// Types can be unwrapped from a \c rosa::deluxe::DeluxeTuple instance as \code /// typename UnwrapDeluxeTuple::Type /// \endcode /// /// For example, the following expression evaluates to `true`: \code /// std::is_same>::Type, /// TypeList>::value /// \endcode ///@{ /// Declaration of the template. /// /// \tparam Tuple \c rosa::deluxe::DeluxeTuple to unwrap template struct UnwrapDeluxeTuple; /// Implementation of the template for \c rosa::deluxe::DeluxeTuple instances. template struct UnwrapDeluxeTuple> { using Type = TypeList; }; ///@} /// \defgroup TypeListUnwrapDeluxeTuple Implementation of /// \c rosa::deluxe::TypeListUnwrapDeluxeTuple /// /// \brief Unwraps element types from instances of \c /// rosa::deluxe::DeluxeTuple in a \c rosa::TypeList. /// /// Types can be unwrapped from \c rosa::deluxe::DeluxeTuple instances as \code /// typename TypeListUnwrapDeluxeTuple::Type /// \endcode /// /// For example, the following expression evaluates to `true`: \code /// std::is_same< /// typename TypeListUnwrapDeluxeTuple, /// T3>>::Type, /// TypeList /// >::value /// \endcode ///@{ /// Declaration of the template. /// /// \tparam List \c rosa::TypeList to check template struct TypeListUnwrapDeluxeTuple; /// Specialization for \c rosa::EmptyTypeList. template <> struct TypeListUnwrapDeluxeTuple { using Type = EmptyTypeList; }; /// Specialization for the case when the first type in \p List is an instance of /// \c rosa::deluxe::DeluxeTuple. template struct TypeListUnwrapDeluxeTuple, Ts...>> { using Type = typename TypeListConcat< typename UnwrapDeluxeTuple>::Type, typename TypeListUnwrapDeluxeTuple>::Type>::Type; }; /// Implementation for a general first type in \p List. template struct TypeListUnwrapDeluxeTuple> { using Type = typename TypeListPush< T, typename TypeListUnwrapDeluxeTuple>::Type>::Type; }; ///@} /// \defgroup IsTuple Implementation of \c rosa::deluxe::IsTuple /// /// \brief Tells if a type is a tuple as in it can be converted to \c /// rosa::deluxe::DeluxeTuple. /// /// \see \c rosa::deluxe::MatchingDeluxeTuple /// /// Whether a type \c T is a tuple can be checked as \code /// IsTuple::Value /// \endcode ///@{ /// Declaration of the template. /// /// \tparam T type to check template struct IsTuple; /// Specialization for the case when the type is an instance of \c std::tuple. template struct IsTuple> { static constexpr bool Value = true; }; /// Specialization for the case when the type is an instance of \c std::tuple. template struct IsTuple> { static constexpr bool Value = true; }; /// Implementation for a general case of type \p T. template struct IsTuple { static constexpr bool Value = false; }; ///@} /// \defgroup IsDeluxeTuple Implementation of \c rosa::deluxe::IsDeluxeTuple /// /// \brief Tells if a type is an instance of \c rosa::deluxe::DeluxeTuple. /// /// Whether a type \c T is an instance of \c rosa::deluxe::DeluxeTuple can be /// checked as \code /// IsDeluxeTuple::Value /// \endcode /// /// \note `!IsDeluxeTuple::Value || IsTuple::Value` ///@{ /// Declaration of the template. /// /// \tparam T type to check template struct IsDeluxeTuple; /// Specialization for the case when the type is an instance of \c /// rosa::deluxe::DeluxeTuple. template struct IsDeluxeTuple> { static constexpr bool Value = true; }; /// Implementation for a general case of type \p T. template struct IsDeluxeTuple { static constexpr bool Value = false; }; ///@} /// \defgroup MatchingDeluxeTuple Implementation of \c /// rosa::deluxe::MatchingDeluxeTuple /// /// \brief Gives the \c rosa::deluxe::DeluxeTuple type that matches a given /// tuple type. /// /// The matching \c rosa::deluxe::DeluxeTuple type for a tuple type \p T can be /// obtained as \code /// typename MatchingDeluxeTuple::Type /// \endcode /// If \p T is \c rosa::deluxe::DeluxeTuple, the matching type is \p T itself. /// If \p T is \c std::tuple, the matching type if \c rosa::deluxe::DeluxeTuple /// with the same type parameters as \p T. /// \c rosa::deluxe::MatchingDeluxeTuple is not defined for other type /// parameters. /// /// \note The template is defined for type \p T only if /// `rosa::deluxe::IsTuple::Value`. Values of such types can be used to /// construct a new instance of the class \c rosa::deluxe::DeluxeTuple. /// ///\see \c rosa::deluxe::IsTuple ///@{ /// Declaration of the template. /// /// \tparam T type to check template struct MatchingDeluxeTuple; /// Specialization for the case when the type is an instance of \c /// rosa::deluxe::DeluxeTuple. template struct MatchingDeluxeTuple> { using Type = DeluxeTuple; }; /// Specialization for the case when the type is an instance of \c /// std::tuple. template struct MatchingDeluxeTuple> { using Type = DeluxeTuple; }; ///@} /// Convenience template type alias for easy use of \c /// rosa::deluxe::MatchingDeluxeTuple. /// /// Converts a tuple type to the matching \c rosa::deluxe::DeluxeTuple type. /// /// \tparam Tuple type to convert template using matching_deluxe_tuple_t = typename MatchingDeluxeTuple::Type; /// \defgroup TypeListAllDeluxeTuple Implementation of /// \c rosa::deluxe::TypeListAllDeluxeTuple /// /// \brief Tells if all types in a \c rosa::TypeList is an instance of \c /// rosa::deluxe::DeluxeTuple. /// /// Whether a \c rosa::TypeList \c List contains instances of \c /// rosa::deluxe::DeluxeTuple only can be checked as \code /// TypeListAllDeluxeTuple::Value /// \endcode ///@{ /// Declaration of the template. /// /// \tparam List \c rosa::TypeList to check template struct TypeListAllDeluxeTuple; /// Specialization for \c rosa::EmptyTypeList. template <> struct TypeListAllDeluxeTuple { static constexpr bool Value = true; }; /// Implementation for the general case when there is at leasst one element in /// the list. template struct TypeListAllDeluxeTuple> { static constexpr bool Value = IsDeluxeTuple::Value && TypeListAllDeluxeTuple>::Value; }; ///@} } // End namespace deluxe } // End namespace rosa namespace std { /// Dumps a \c rosa::deluxe::Deluxe instance to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to /// \param Tuple \c rosa::deluxe::Deluxe to dump /// /// \return \p OS after dumping \p Tuple to it template ostream &operator<<(ostream &OS, const rosa::deluxe::DeluxeTuple &Tuple) { Tuple.dump(OS); return OS; } } // End namespace std #endif // ROSA_DELUXE_DELUXETUPLE_HPP