/*! * \file utl/meta/basic.h * \brief Template meta-programming basic definitions */ #ifndef __utl_meta_basic_h__ #define __utl_meta_basic_h__ #include #include #include /*! * \ingroup meta * \defgroup basic Basic * Basic definitions */ //! @{ /*! * \ingroup basic * \defgroup meta_core Core * Core definitions */ //! @{ namespace utl { namespace meta { /*! * \brief meta's empty type * * utl::meta's nil type is not pure nil. It's a recursive "de-referencable nil. * Each time someone applies \c \::type to it, he gets back nil_. This way we can prevent * a lot of compilation errors in a wrong meta:: handling. */ struct nil_ { using type = nil_; }; //! Type alias for \c Tp::type. //! Is used to evaluate/extract return type of metafunctions //! \tparam Tp The metafunction to evaluate //! \return The inner \::type template using eval = typename Tp::type; //! Type alias for \c Tp::type::value. //! Is used to evaluate/extract return value of metafunctions //! \tparam Tp The metafunction to evaluate //! \return The inner \::type::value template using eval_v = typename eval::value; //! //! integral_ is a holder class for a compile-time value of an integral type. //! //! Every Integral Constant is also a null-ary Metafunction, returning itself.\n //! An integral constant object is implicitly convertible to the corresponding //! run-time value of the wrapped integral type template using integral_ = std::integral_constant; //! \name Wrappers for basic types //! @{ //! bool_ type: integral constant wrapper for bool template using bool_ = integral_; using true_ = bool_; //!< The type used as a compile-time boolean with true value. using false_ = bool_; //!< The type used as a compile-time boolean with false value. //! int8_ type: integral constant wrapper for \c int8_t template using int8_ = integral_; //! uint8_ type: integral constant wrapper for \c uint8_t template using uint8_ = integral_; //! int16_ type: integral constant wrapper for \c int16_t template using int16_ = integral_; //! uint16_ type: integral constant wrapper for \c uint16_t template using uint16_ = integral_; //! int32_ type: integral constant wrapper for \c int32_t template using int32_ = integral_; //! uint32_ type: integral constant wrapper for \c uint32_t template using uint32_ = integral_; //! char_ type: integral constant wrapper for \c char template using char_ = integral_; //! int_ type: integral constant wrapper for \c int template using int_ = integral_; //! long_ type: integral constant wrapper for \c long template using long_ = integral_; //! index_ type: integral constant wrapper for \c index_t a.k.a std::size_t template using index_ = integral_; //! size_ type: integral constant wrapper for \c size_t a.k.a std::size_t template using size_ = integral_; //! The last position we can express for indexing using Npos = size_; //! @} //! \name unevaluated expressions //! @{ //! Computes the size of the type \p Tp. //! Complexity \f$ O(1) \f$. template using sizeof_ = size_; //! Computes the alignment required for any instance of the type \p Tp. //! Complexity \f$ O(1) \f$. template using alignof_ = size_; //! @} //! \name integer sequence //! @{ template< class Tp, Tp... Ints > using integer_sequence = std::integer_sequence; template using make_integer_sequence = std::make_integer_sequence; //! Alias template index_sequence template using index_sequence = integer_sequence; //! Alias template make_index_sequence template using make_index_sequence = make_integer_sequence ; //! Alias template index_sequence_for template using index_sequence_for = make_index_sequence; //! @} }} //!@} /*! * \ingroup basic * \defgroup selection Selection * Type selection support header */ //! @{ namespace utl { namespace meta{ //! \name if implementation //! @{ namespace details { template struct if_c_ { using type = nil_; //< avoid ill formed result }; template struct if_c_ { using type = Then; }; template struct if_c_ { using type = Then; }; template struct if_c_ { using type = Else; }; } //! Select one type or another depending on a compile-time Boolean. template using if_c = eval>; //! Select one type or another depending on a compile-time Boolean type template using if_ = if_c; //! @} /*! * \name Named type selectors */ //! @{ //! Select the first type of a type sequence template using first_of = T1; //! Select the second type of a type sequence template using second_of = T2; //! @} }} //! @} /*! * \ingroup basic * \defgroup logic_operations Logic Operations * logic operators and type relations support */ //! @{ namespace utl { namespace meta{ /*! * \name Logical relation for types */ //! @{ //! Negate the *bool* constant parameter and return bool_ template using not_c = bool_; //! negate the bool_ parameter and return bool_ template using not_ = not_c; //! \name OR implementation //! @{ namespace details { template struct _or_; template<> struct _or_<> : false_ { }; template struct _or_ : T1 { }; template struct _or_ : if_ { }; template struct _or_ : if_> { }; } //! Operator or for bool_ types //! \tparam Ts Variadic args of type bool_ //! \return Logical or as bool_ template using or_ = eval>; //! @} //! \name AND implementation //! @{ namespace details { template struct _and_; template<> struct _and_<> : true_ { }; template struct _and_ : T1 { }; template struct _and_ : if_ { }; template struct _and_ : if_, T1> { }; } //! Operator and for bool_ types //! \tparam Ts Variadic args of type bool_ //! \return Logical and as bool_ template using and_ = eval>; //! @} //! \name same //! @{ template struct same_ : false_ { }; template struct same_ : true_ { }; template using not_same_ = not_>>; //! @} //! @} }} //! @} /*! * \ingroup basic * \defgroup integral_operators integral operators * Type arithmetic and operations */ //! @{ namespace utl { namespace meta { /*! * \name Math operations */ //! @{ //! Negation template using negate = integral_; //! Addition template using add = integral_< decltype(Tp1() + Tp2()), Tp1() + Tp2() >; //! Multiplication template using mult = integral_< decltype(Tp2() * Tp2()), Tp1() * Tp2() >; //! Division template using divide = integral_< decltype(Tp2() / Tp2()), Tp1() / Tp2() >; //! Modulo template using modulo = integral_< decltype(Tp1() % Tp2()), Tp1() % Tp2() >; //! Substruction template using sub = add>; //! Increase template using inc = add>; //! decrease template using dec = add>; //! @} /*! * \name Comparison operations */ //! @{ //! \return a true-valued Integral Constant if Tp1 and Tp2 are equal. template using comp_eq = bool_; //! \return a true-valued Integral Constant if Tp1 is less than Tp2. template using comp_lt = bool_<(Tp1() < Tp2())>; //! Not equal template using comp_ne = not_>; //! Greater than template using comp_gt = comp_lt ; //! Less or equal template using comp_le = not_>; //! Greater or equal template using comp_ge = not_>; //! @} /*! * \name Bitwise operations */ //! @{ //! \return bitwise not (~) operation of its argument. template using bitnot_ = integral_; //! \return bitwise and (&) operation of its arguments template using bitand_ = integral_; //! \return bitwise or (|) operation of its arguments. template using bitor_ = integral_; //! \return bitwise xor (^) operation of its arguments. template using bitxor_ = integral_; //! \return the result of bitwise shift left (<<) operation on Tp. template using shift_left = integral_; //! \return the result of bitwise shift right (>>) operation on Tp. template using shift_right = integral_> shift())>; //! @} }} //! @} //! @} #endif /* __utl_meta_basic_h__ */