diff --git a/include/utl/impl/concepts.h b/include/utl/core/concepts/concepts.h
similarity index 100%
rename from include/utl/impl/concepts.h
rename to include/utl/core/concepts/concepts.h
diff --git a/include/utl/helper/crtp.h b/include/utl/core/crtp.h
similarity index 100%
rename from include/utl/helper/crtp.h
rename to include/utl/core/crtp.h
diff --git a/include/utl/impl/impl.h b/include/utl/core/impl.h
similarity index 100%
rename from include/utl/impl/impl.h
rename to include/utl/core/impl.h
diff --git a/include/utl/impl/types.h b/include/utl/core/types.h
similarity index 100%
rename from include/utl/impl/types.h
rename to include/utl/core/types.h
diff --git a/include/utl/impl/version.h b/include/utl/core/version.h
similarity index 100%
rename from include/utl/impl/version.h
rename to include/utl/core/version.h
diff --git a/include/utl/meta/idx_sequence.h b/include/utl/meta/idx_sequence.h
new file mode 100644
index 0000000..19b1dcc
--- /dev/null
+++ b/include/utl/meta/idx_sequence.h
@@ -0,0 +1,113 @@
+/*!
+ * \file pack.h
+ * \brief Template meta-programming parameter pack container
+ *
+ * Copyright (C) 2018 Christos Choutouridis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#ifndef __utl_meta_idx_sequence_h__
+#define __utl_meta_idx_sequence_h__
+
+#include
+#include
+
+
+/*!
+ * \ingroup meta
+ * \defgroup index_sequence
+ */
+//! @{
+
+namespace utl {
+namespace meta {
+
+ /*!
+ * Class template integer_sequence
+ */
+ template
+ struct integer_sequence {
+ using value_type = _Tp;
+ static constexpr size_t size() noexcept {
+ return sizeof...(_Idx);
+ }
+ };
+
+ //! Alias template index_sequence
+ template
+ using index_sequence = integer_sequence;
+
+ //! make_integer_sequence
+ //! @{
+ namespace detail {
+ // Stores a tuple of indices
+ template struct index_tuple { };
+
+ // Concatenates two index_tuples.
+ template struct it_cat_;
+
+ template
+ struct it_cat_ , index_tuple> {
+ using type = index_tuple;
+ };
+
+ // Builds an index_tuple<0, 1, 2, ..., _Num-1>.
+ template
+ struct make_index_tuple_
+ : it_cat_>,
+ type_>>
+ { };
+ // termination specialization for 1
+ template<>
+ struct make_index_tuple_<1> {
+ using type = index_tuple<0>;
+ };
+ // termination specialization for 0
+ template<>
+ struct make_index_tuple_<0> {
+ using type = index_tuple<>;
+ };
+
+ // factory type
+ template>>
+ struct make_integer_sequence_;
+
+ template
+ struct make_integer_sequence_<_Tp, _Num, index_tuple<_Idx...>> {
+ static_assert( _Num >= 0,
+ "Cannot make integer sequence of negative length" );
+ using type = integer_sequence<_Tp, static_cast<_Tp>(_Idx)...>;
+ };
+ }
+ //! Alias template make_integer_sequence
+ //! Complexity \f$ O(log N) \f$
+ template
+ using make_integer_sequence = type_>;
+
+ //! Alias template make_index_sequence
+ //! Complexity \f$ O(log N) \f$
+ template
+ using make_index_sequence = make_integer_sequence;
+
+ //! Alias template index_sequence_for
+ //! Complexity \f$ O(log N) \f$
+ //! where N is sizeof...(_Ts)
+ template
+ using index_sequence_for = make_index_sequence;
+ //! @}
+
+}}
+//! @}
+#endif /* __utl_meta_idx_sequence_h__ */
diff --git a/include/utl/meta/integral.h b/include/utl/meta/integral.h
index 11a2993..4dda51b 100644
--- a/include/utl/meta/integral.h
+++ b/include/utl/meta/integral.h
@@ -1,5 +1,5 @@
/*!
- * \file integral.h
+ * \file integralconstant.h
* \brief Template meta-programming integral constant
*
* Copyright (C) 2018 Christos Choutouridis
@@ -17,38 +17,102 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
-#ifndef __utl_meta_integral_h__
-#define __utl_meta_integral_h__
+#ifndef __utl_meta_integralconstant_h__
+#define __utl_meta_integralconstant_h__
+
+#include
-#include
/*!
* \ingroup meta
* \defgroup integral
- * integral constand support header
+ * integral constant support header
*/
//! @{
namespace utl {
+namespace meta {
+
+ //! Empty type
+ struct nil_ { };
+
+ //! Type alias for \p _Tp::type. Used to extract return type of metafunctions
+ template
+ using type_ = typename _Tp::type;
//! integral_constant
+ //! An Integral Constant is a holder class for a compile-time value of an integral type.
+ //! Every Integral Constant is also a nullary Metafunction, returning itself.
+ //! An integral constant object is implicitly convertible to the corresponding
+ //! run-time value of the wrapped integral type
+ //! @{
template
- struct integral_ {
+ struct integral_constant {
using value_type = _Tp;
- using type = integral_<_Tp, _v>;
+ using type = integral_constant<_Tp, _v>;
- constexpr operator value_type() const {
+ constexpr operator value_type() const noexcept {
return value;
}
- constexpr value_type operator()() const {
+ constexpr value_type operator()() const noexcept {
return value;
}
static constexpr _Tp value = _v;
};
template
- constexpr _Tp integral_<_Tp, _v>::value;
-}
+ constexpr _Tp integral_constant<_Tp, _v>::value;
+ //! @}
+
+ //! Wrappers for basic types
+ //! @{
+
+ //! integral constant
+ template
+ using integral_c = integral_constant<_Tp, _v>;
+
+ //! bool_ type: integral constant wrapper for bool
+ template
+ using bool_ = integral_c;
+
+ 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.
+
+ //! char_ type: integral constant wrapper for \c char
+ template
+ using char_ = integral_c;
+
+ //! int_ type: integral constant wrapper for \c int
+ template
+ using int_ = integral_c;
+
+ //! long_ type: integral constant wrapper for \c long
+ template
+ using long_ = integral_c;
+
+ //! index_t_ type: integral constant wrapper for \c index_t a.k.a std::size_t
+ template
+ using index_t_ = integral_c;
+
+ //! size_t_ type: integral constant wrapper for \c size_t a.k.a std::size_t
+ template
+ using size_t_ = integral_constant;
+
+ //! Computes the size of the type \p _Tp.
+ //! Complexity \f$ O(1) \f$.
+ template
+ using sizeof_ = size_t_;
+
+ //! Computes the alignment required for any instance of the type \p _Tp.
+ //! Complexity \f$ O(1) \f$.
+ template
+ using alignof_ = size_t_;
+ //! @}
+
+ //! The last position we can express for indexing
+ using Npos = size_t_;
+
+}}
//!@}
-#endif /* __utl_meta_integral_h__ */
+#endif /* __utl_meta_integralconstant_h__ */
diff --git a/include/utl/meta/invoke.h b/include/utl/meta/invoke.h
new file mode 100644
index 0000000..2211b47
--- /dev/null
+++ b/include/utl/meta/invoke.h
@@ -0,0 +1,63 @@
+/*!
+ * \file void.h
+ * \brief Template meta-programming void helpers
+ *
+ * Copyright (C) 2018 Christos Choutouridis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#ifndef __utl_meta_void_h__
+#define __utl_meta_void_h__
+
+#include
+#include
+
+/*! \ingroup meta
+ * \defgroup void
+ * void_ support header
+ */
+//! @{
+
+namespace utl {
+
+ /*!
+ * Like boost::mpl we made void_ a complete type to allow it to be
+ * instantiated so that it can be passed in as an object that can be
+ * used to select an overloaded function.
+ */
+ struct void_ {
+ typedef void_ type;
+ };
+
+ template
+ struct is_void_
+ : false_ { };
+
+ template<>
+ struct is_void_
+ : true_ { };
+
+ template
+ struct is_not_void_
+ : true_ { };
+
+ template<>
+ struct is_not_void_
+ : false_ { };
+
+}
+
+//!@}
+
+#endif /* __utl_meta_void_h__ */
diff --git a/include/utl/meta/logical.h b/include/utl/meta/logical.h
index 6b8ce35..79c6df3 100644
--- a/include/utl/meta/logical.h
+++ b/include/utl/meta/logical.h
@@ -20,9 +20,8 @@
#ifndef __utl_meta_logical_h__
#define __utl_meta_logical_h__
-#include
-#include
-#include
+#include
+#include
/*!
* \ingroup meta
@@ -31,51 +30,69 @@
*/
//! @{
namespace utl {
+namespace meta{
- //! NOT implementation
- template
- struct not_ : bool_ { };
+ /*!
+ * Logical relation for types
+ */
+ //! @{
+
+ //! Negate the *bool* constant parameter
+ template
+ using not_c = bool_;
+
+ //! not
+ template
+ using not_ = not_c<_Tp::type::value>;
//! OR implementation
//! @{
- template struct or_;
+ namespace detail {
+ template struct _or_;
- template<>
- struct or_<>
- : false_ { };
+ template<>
+ struct _or_<> : false_ { };
- template
- struct or_<_T1>
- : _T1 { };
+ template
+ struct _or_<_T1> : _T1 { };
- template
- struct or_ <_T1, _T2>
- : select_<_T1::value, _T1, _T2> { };
+ template
+ struct _or_ <_T1, _T2>
+ : if_<_T1, _T1, _T2> { };
+
+ template
+ struct _or_<_T1, _T2, _T3, _Tn...>
+ : if_<_T1, _T1, _or_<_T2, _T3, _Tn...>> { };
+ }
- template
- struct or_<_T1, _T2, _T3, _Tn...>
- : select_<_T1::value, _T1, or_<_T2, _T3, _Tn...>> { };
+ template
+ using or_ = type_>;
//! @}
//! AND implementation
//! @{
- template struct and_;
+ namespace detail {
+ template struct _and_;
- template<>
- struct and_<>
- : true_ { };
+ template<>
+ struct _and_<>
+ : true_ { };
- template
- struct and_ <_T1>
- : _T1 { };
+ template
+ struct _and_ <_T1>
+ : _T1 { };
- template
- struct and_<_T1, _T2>
- : select_<_T1::value, _T2, _T1> { };
+ template
+ struct _and_<_T1, _T2>
+ : if_<_T1, _T2, _T1> { };
+
+ template
+ struct _and_<_T1, _T2, _T3, _Tn...>
+ : if_<_T1, _and_<_T2, _T3, _Tn...>, _T1> { };
+ }
- template
- struct and_<_T1, _T2, _T3, _Tn...>
- : select_<_T1::value, and_<_T2, _T3, _Tn...>, _T1> { };
+ template
+ using and_ = type_>;
//! @}
//! same
@@ -90,11 +107,12 @@ namespace utl {
//! not same
//! @{
template
- struct not_same_ : true_ { };
+ using not_same_ = not_>>;
+ //! @}
- template
- struct not_same_ <_Tp, _Tp> : false_ { };
//! @}
-}
+}}
+
+//! @}
#endif /* __utl_meta_logical_h__ */
diff --git a/include/utl/meta/meta.h b/include/utl/meta/meta.h
new file mode 100644
index 0000000..16966e5
--- /dev/null
+++ b/include/utl/meta/meta.h
@@ -0,0 +1,33 @@
+/*!
+ * \file /utl/core/version.h
+ * \brief version and cpp version checks
+ *
+ * Copyright (C) 2018 Christos Choutouridis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifndef __utl_meta_meta_h__
+#define __utl_meta_meta_h__
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#endif /* __utl_meta_meta_h__ */
diff --git a/include/utl/meta/operations.h b/include/utl/meta/operations.h
new file mode 100644
index 0000000..595f3f7
--- /dev/null
+++ b/include/utl/meta/operations.h
@@ -0,0 +1,132 @@
+/*!
+ * \file operators.h
+ * \brief Template meta-programming integral constant arithmetic
+ *
+ * Copyright (C) 2018 Christos Choutouridis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#ifndef __utl_meta_arithmetic_h__
+#define __utl_meta_arithmetic_h__
+
+#include
+#include
+
+/*!
+ * \ingroup meta
+ * \defgroup integral operators
+ * Type arithmetic and operators
+ */
+//! @{
+
+namespace utl {
+namespace meta {
+
+ /*!
+ * Math operations
+ * requires IntegralConstant(_Tp)
+ */
+ //! @{
+
+ //! Negation
+ template
+ using negate = integral_constant;
+ //! Addition
+ template
+ using add = integral_constant<
+ decltype(_Tp1() + _Tp2()),
+ _Tp1() + _Tp2()
+ >;
+ //! Multiplication
+ template
+ using mult = integral_constant<
+ decltype(_Tp2() * _Tp2()),
+ _Tp1() * _Tp2()
+ >;
+ //! Division
+ template
+ using divide = integral_constant<
+ decltype(_Tp2() / _Tp2()),
+ _Tp1() / _Tp2()
+ >;
+ //! Modulo
+ template
+ using modulo = integral_constant<
+ decltype(_Tp1() % _Tp2()),
+ _Tp1() % _Tp2()
+ >;
+ //! Substruction
+ template
+ using sub = add<_Tp1, negate<_Tp2>>;
+
+ //! Increase
+ template
+ using inc = add<_Tp, int_<1>>;
+
+ //! decrease
+ template
+ using dec = add<_Tp, int_<-1>>;
+
+ //! @}
+
+ /*!
+ * Comparison operations
+ * requires IntegralConstant(_Tp)
+ */
+ //! @{
+
+ //! \return a true-valued Integral Constant if _Tp1 and _Tp2 are equal.
+ template using comp_eq = bool_<_Tp1() == _Tp2()>;
+ //! \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 <_Tp2, _Tp1>;
+ //! Less or equal
+ template using comp_le = not_>;
+ //! Greater or equal
+ template using comp_ge = not_>;
+ //! @}
+
+ /*!
+ * Bitwise operations
+ * requires IntegralConstant(_Tp)
+ */
+ //! @{
+
+ //! \return bitwise not (~) operation of its argument.
+ template using bitnot_ = integral_c;
+ //! \return bitwise and (&) operation of its arguments
+ template
+ using bitand_ = integral_c;
+ //! \return bitwise or (|) operation of its arguments.
+ template
+ using bitor_ = integral_c;
+
+ //! \return bitwise xor (^) operation of its arguments.
+ template
+ using bitxor_ = integral_c;
+ //! \return the result of bitwise shift left (<<) operation on _Tp.
+ template
+ using shift_left = integral_c;
+ //! \return the result of bitwise shift right (>>) operation on _Tp.
+ template
+ using shift_right = integral_c> shift()), (_Tp() >> shift())>;
+ //! @}
+}}
+//!@}
+
+#endif /* __utl_meta_integral_h__ */
diff --git a/include/utl/meta/selection.h b/include/utl/meta/selection.h
new file mode 100644
index 0000000..15fe781
--- /dev/null
+++ b/include/utl/meta/selection.h
@@ -0,0 +1,74 @@
+/*!
+ * \file selection.h
+ * \brief Template meta-programming type selections.
+ *
+ * Copyright (C) 2018 Christos Choutouridis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#ifndef __utl_meta_selection_h__
+#define __utl_meta_selection_h__
+
+#include
+#include
+#include
+
+/*!
+ * \ingroup meta
+ * \defgroup type selection
+ * Type selection support header
+ */
+//! @{
+namespace utl {
+namespace meta{
+
+ /*!
+ * Type selection
+ */
+ //! @{
+
+ //! if_, if_c
+ //! @{
+ namespace detail {
+ 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 = type_>;
+
+ //! Select one type or another depending on a compile-time Boolean type
+ template
+ using if_ = if_c;
+
+ //! @}
+}}
+
+//! @}
+
+#endif /* __utl_meta_selection_h__ */
diff --git a/include/utl/meta/sfinae.h b/include/utl/meta/sfinae.h
index 9ec6dc1..27f775c 100644
--- a/include/utl/meta/sfinae.h
+++ b/include/utl/meta/sfinae.h
@@ -1,5 +1,5 @@
/*!
- * \file use.h
+ * \file sfinae.h
* \brief Template meta-programming SFINAE helpers
*
* Copyright (C) 2018 Christos Choutouridis
@@ -17,72 +17,57 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
-#ifndef __utl_meta_use_h__
-#define __utl_meta_use_h__
-
-#include
-#include
+#ifndef __utl_meta_sfinae_h__
+#define __utl_meta_sfinae_h__
+#include
/*!
* \ingroup meta
- * \defgroup use
- * conditional use support header. This is a SFINAE helper
+ * \defgroup sfinae
+ * conditional use support header.
*/
//! @{
namespace utl {
+namespace meta {
- /*!
- * void_t
- * Utility meta-function that maps a sequence of any types to the type void
- * \note The idea is:
- * template
- * using void_t = void;
- *
- * Until CWG 1558 (a C++14 defect), unused parameters in alias templates were not
- * guaranteed to ensure SFINAE and could be ignored, so earlier compilers require
- * a more complex definition of void_t, such as the following implementation
- * https://en.cppreference.com
- */
+ //! Tool to enable a partial specialization only if a boolean condition is true.
//! @{
- template
- struct void_t_impl {
- typedef void type;
- };
- //! The actual void_t type alias
- template
- using void_t = typename void_t_impl<_Ts...>::type;
+ namespace detail {
+ template
+ struct when_ { };
+ template <> struct when_ { using type = void; };
+ }
+ //! Well formed only if \p If is true
+ template
+ using when = type_>;
//! @}
- //! Alias template for if_
- template
- using if_t = typename if_<_Check, _Tp>::type;
-
- //! Publicly recognized alias template for if_
- template
- using enable_if_t = typename if_<_Check, _Tp>::type;
-
- //! Uniform alias template for if_
- template
- using use_if_t = typename if_<_Check, _Tp>::type;
-
- //! If same type resolves to _Ret, else SFINAE
- template
- using use_if_same_t = typename if_::value, _Ret>::type;
+ //! select _Tp if \p If is true, else SFINAE
+ //! We implement eneble_if so we don't have to pull entire \c from stl
+ //! @{
+ template
+ struct enable_if {
+ using type = _Tp;
+ };
+ template
+ struct enable_if { /* SFINAE*/ };
- //! If not same type resolves to _Ret, else SFINAE
- template
- using use_if_not_same_t = typename if_::value, _Ret>::type;
+ //! Alias template for enable_if
+ template
+ using use_if = enable_if;
- //! If any type (_T1 or _T2) type resolves to _Ret, else to SFINAE
- template
- using use_if_any_t = typename if_::value, _Ret>::type;
+ //! Publicly recognized alias template for enable_if
+ template
+ using enable_if_t = type_>;
- //! If both type (_T1 and _T2) type resolves to _Ret, else to SFINAE
- template
- using use_if_both_t = typename if_::value, _Ret>::type;
+ //! Uniform alias template for use_if
+ template
+ using use_if_t = type_>;
+ //! @}
-}
+}}
//! @}
-#endif /* __utl_meta_use_h__ */
+
+#endif /* __utl_meta_sfinae_h__ */
diff --git a/include/utl/meta/typelist.h b/include/utl/meta/typelist.h
new file mode 100644
index 0000000..d490b3d
--- /dev/null
+++ b/include/utl/meta/typelist.h
@@ -0,0 +1,420 @@
+/*!
+ * \file typelist.h
+ * \brief A template parameter "container"
+ *
+ * Copyright (C) 2018 Christos Choutouridis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#ifndef __utl_meta_pack_h__
+#define __utl_meta_pack_h__
+
+#include
+#include
+#include
+#include
+#include
+
+/*!
+ * \ingroup meta
+ * \defgroup typelist
+ */
+//! @{
+
+namespace utl {
+namespace meta {
+
+ /*!
+ * A class template that just holds a parameter pack.
+ * The idea came from MPL's sequence concept[1] and from N4115[2].
+ * In addition to N4115's name "packer" we just prefer a name which is object, not a subject.
+ * This way the name gives the feeling of a container and smells like Python.
+ *
+ * In addition to tuple we lack members, so typelist could serve as an empty base class,
+ * and an object of the ultimate type could always be instantiated
+ * (even if the parameter typelist contains void or some type that lacks
+ * a default constructor).
+ * ex:
+ * using l1 = typelist;
+ *
+ * boost::hana[3] suggest a more powerful scheme were type invariant structures can be used
+ * for metaprograming also. This lib does not need (yet) this kind of power (we afraid the
+ * responsibility that comse along). So a simple python-like list with some extra vector-like
+ * element access functionalities and no iterators is good enough(for now).
+ *
+ * [1]: https://www.boost.org/doc/
+ * [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html
+ * [3]: https://github.com/boostorg/hana
+ */
+ template
+ struct typelist {
+ using type = typelist; //!< act as identity
+
+ //! \return sizeof...(Ts)
+ static constexpr size_t size() noexcept {
+ return sizeof...(Ts);
+ }
+ //! \return true if empty
+ static constexpr bool empty() noexcept {
+ return (sizeof...(Ts) == 0);
+ }
+ };
+
+ /*!
+ * An integral constant wrapper that is the size of the \c meta::typelist
+ * Complexity \f$ O(1) \f$.
+ * \param List A typelist
+ * \return The size of the typelist
+ */
+ template
+ using size = size_t_;
+
+ /*!
+ * An Boolean constant wrapper that returns if the typelist is empty
+ * Complexity \f$ O(1) \f$.
+ * \param List A typelist
+ * \return Empty or not
+ */
+ template
+ using empty = bool_;
+
+ //! pair
+ //! A special typelist with only 2 Types
+ //! @{
+ template
+ using pair = typelist;
+
+ //! @}
+
+ //! apply
+ //! like:
+ //! template
+ //! constexpr decltype(auto) apply(F&& f, Tuple&& t);
+ namespace detail {
+ template
+ struct apply_ { };
+
+ // apply Param =Ret(Args...)
+ template
+ struct apply_
+ : invoke { };
+ // apply Param = F
+ template class F, typename... Args>
+ struct apply_>
+ : invoke { };
+ // apply Param = integer_sequence
+ template
+ struct apply_>
+ : invoke...> { };
+ }
+
+ //! Apply the Invocable \p Fn using the types in the type \p Param as arguments.
+ template
+ using apply = detail::apply_;
+
+ //! @}
+
+ /*
+ * ========= typelist operations =========
+ */
+ //! fold, rev_fold
+ //! @{
+ namespace detail {
+ // fold<, V, F> == F, T2>, T3>
+ template
+ struct fold_ { }; // ill formed
+
+ // recursive call
+ template
+ struct fold_, V, Fn> {
+ using type = type_<
+ fold_<
+ typelist,
+ invoke,
+ Fn
+ >
+ >;
+ };
+ // termination call
+ template
+ struct fold_, V0, Fn> {
+ using type = V0;
+ };
+
+ // rev_fold<, V, F> == F>>
+ template
+ struct rev_fold_ { }; // ill formed
+
+ // recursive call
+ template
+ struct rev_fold_, V, Fn> {
+ using type = invoke <
+ Fn, Head, type_<
+ rev_fold_ <
+ typelist,
+ V,
+ Fn
+ >
+ >
+ >;
+ };
+ // termination call
+ template
+ struct rev_fold_ , V, Fn> {
+ using type = invoke;
+ };
+ // termination call
+ template
+ struct rev_fold_ , V, Fn> {
+ using type = invoke;
+ };
+ }
+
+ /*!
+ * transform the \p List to a new one by doing a left fold using binary Invocable \p Fn
+ * and initial value \p V
+ * Complexity \f$ O(N) \f$
+ * \param List The list to fold
+ * \param V The initial item feeded to Fn
+ * \param Fn The binary Invocable
+ */
+ template
+ using fold = type_>;
+
+ //! accumulate is an stl name for fold
+ template
+ using accumulate = fold;
+
+ /*!
+ * transform the \p List to a new one by doing a left fold using binary Invocable \p Fn
+ * and initial value \p V
+ * Complexity \f$ O(N) \f$
+ * \param List The list to fold
+ * \param V The initial item feeded to Fn
+ * \param Fn The binary Invocable
+ */
+ template
+ using rev_fold = type_>;
+ //! @}
+
+ //! Concatenation
+ //! @{
+ namespace detail {
+ template
+ struct concat_ { };
+
+ template <>
+ struct concat_<> {
+ using type = typelist<>;
+ };
+
+ template
+ struct concat_> {
+ using type = typelist;
+ };
+
+ template
+ struct concat_, typelist> {
+ using type = typelist;
+ };
+
+ template
+ struct concat_, typelist, typelist> {
+ using type = typelist;
+ };
+
+ template
+ struct concat_, typelist, typelist, Rest...>
+ : concat_, Rest...> { };
+
+ template
+ struct concat_, typelist, typelist, typelist, Rest...>
+ : concat_, Rest...> { };
+
+ }
+
+ /*!
+ * Transformation that concatenates several lists into a single typelist.
+ * The parameters must all be instantiations of \c meta::typelist.
+ * Complexity: \f$ O(L) \f$
+ * where \f$ L \f$ is the number of lists in the typelist of lists.
+ */
+ template
+ using concat = type_>;
+ //! @}
+
+ //! Transform
+ //! @{
+ namespace detail {
+ template
+ struct transform_ { };
+
+ template
+ struct transform_, Fn>, void_...>> {
+ using type = typelist