diff --git a/include/utl/concepts/concepts.h b/include/utl/concepts/concepts.h
new file mode 100644
index 0000000..e6c2784
--- /dev/null
+++ b/include/utl/concepts/concepts.h
@@ -0,0 +1,34 @@
+/*!
+ * \file /utl/concepts/concepts.h
+ * \brief Concepts main include header
+ *
+ * Copyright (C) 2018-2019 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_concepts_concepts_h__
+#define __utl_consepts_concepts_h__
+
+#include
+
+#include
+#include
+#include
+
+/*!
+ * \defgroup concepts
+ */
+
+#endif /* __utl_concepts_concepts_h__ */
diff --git a/include/utl/concepts/defines.h b/include/utl/concepts/defines.h
new file mode 100644
index 0000000..58aac8c
--- /dev/null
+++ b/include/utl/concepts/defines.h
@@ -0,0 +1,69 @@
+/*!
+ * \file /utl/concepts/defines.h
+ * \brief Concepts defines
+ *
+ * Copyright (C) 2018-2019 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_concepts_defines_h__
+#define __utl_concepts_defines_h__
+
+//!\defgroup concepts
+//!@{
+
+/*!
+ * \brief
+ * utl typename constraints wrapper
+ *
+ * \example
+ * \code
+ * template struct lala { };
+ * // will expand to something like:
+ * // template struct lala { };
+ * // or
+ * // template struct lala { };
+ * \endcode
+ */
+#if CXX_CONCEPTS
+ #define utlConstrainType(_Concept_) _Concept_
+#else
+ #define utlConstrainType(_Concept_) typename
+#endif
+
+/*! \brief
+ * utl concept keyword syntax wrapper
+ */
+#if CXX_CONCEPTS
+ #if __cpp_concepts <= 201507L
+ #define _utlConcept concept bool
+ #else
+ #define _utlConcept concept
+ #endif
+#else
+ #define _utlConcept constexpr bool
+#endif
+
+#ifndef CXX_LIB_INVOKE
+ #ifdef __cpp_lib_invoke
+ #define CXX_LIB_INVOKE __cpp_lib_invoke
+ #else
+ #define CXX_LIB_INVOKE 0
+ #endif
+#endif
+
+//! @}
+
+#endif /* __utl_concepts_defines_h__ */
diff --git a/include/utl/concepts/iterators.h b/include/utl/concepts/iterators.h
new file mode 100644
index 0000000..e0965d8
--- /dev/null
+++ b/include/utl/concepts/iterators.h
@@ -0,0 +1,70 @@
+/*!
+ * \file /utl/impl/concepts/iterators.h
+ * \brief utl iterator concept support header
+ *
+ * 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_concepts_iterator_h__
+#define __utl_concepts_iterator_h__
+
+#include
+#include
+#include
+
+/*!
+ * \ingroup concepts
+ * \defgroup iterators
+ */
+//! @{
+namespace utl {
+
+ #if CXX_CONCEPTS
+ template
+ _utlConcept WeaklyIncrementable =
+ Semiregular &&
+ requires(I i) {
+ { ++i } -> Same&; // not required to be equality preserving
+ i++; // not required to be equality preserving
+ };
+ #else
+ namespace detail {
+ template using try_ppI = decltype (++(std::declval()));
+ template using try_Ipp = decltype (std::declval()++);
+ }
+ template
+ _utlConcept WeaklyIncrementable =
+ Semiregular
+ && Same<_ref_t, meta::detected_t>>
+ && meta::is_detected>::value;
+ #endif
+
+ #if CXX_CONCEPTS
+ template
+ _utlConcept DeviceIterator =
+ requires(I i) {
+ { *i } -> auto&&; // Requires: i is dereferenceable
+ } &&
+ WeaklyIncrementable;
+
+ #else
+
+ #endif
+
+}
+
+//! @}
+#endif /* __utl_concepts_iterator_h__ */
diff --git a/include/utl/concepts/stl.h b/include/utl/concepts/stl.h
new file mode 100644
index 0000000..6b4d445
--- /dev/null
+++ b/include/utl/concepts/stl.h
@@ -0,0 +1,751 @@
+/*!
+ * \file /utl/concepts/stl.h
+ * \brief STL's Concepts
+ *
+ * Copyright (C) 2018 - 2019 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_concepts_stl_h__
+#define __utl_concepts_stl_h__
+
+#include
+#include
+#include
+
+#include
+
+/*!
+ * \brief
+ * STL's core language concepts
+ *
+ * We provide std concepts in case host's stl does not provide them yet.
+ *
+ * For more information \see https://en.cppreference.com/w/cpp/concepts
+ */
+//! @{
+namespace utl {
+
+ template
+ using remove_cvref_t = std::remove_cv_t< std::remove_reference_t >;
+
+ template
+ using cref_ = const std::remove_reference_t&;
+
+ template
+ using _ref_t = std::add_lvalue_reference_t;
+
+ /*!
+ * Same
+ */
+ template
+ _utlConcept Same = meta::same_::value;
+
+// template
+// _utlConcept Decayed = Same>;
+
+ /*!
+ * DerivedFrom
+ */
+ template
+ _utlConcept DerivedFrom =
+ std::is_base_of::value &&
+ std::is_convertible::value;
+
+
+ /*!
+ * ConvertibleTo
+ */
+ template
+ #if CXX_CONCEPTS
+ _utlConcept ConvertibleTo =
+ std::is_convertible::value &&
+ requires(From (&f)()) {
+ static_cast(f());
+ };
+ #else
+ _utlConcept ConvertibleTo = std::is_convertible::value;
+ #endif
+
+ /*!
+ * Common Reference
+ */
+ //! @{
+ namespace common_impl {
+ //! \see https://ericniebler.github.io/std/wg21/D0022.html
+ // ========== common reference ===========
+ template
+ using __cond_res =
+ decltype(false ? std::declval()() : std::declval()());
+
+ template
+ struct __copy_cv_ {
+ static_assert(!std::is_reference::value);
+ template using apply = To;
+ };
+ template
+ struct __copy_cv_ {
+ template using apply = const To;
+ };
+ template
+ struct __copy_cv_ {
+ template using apply = volatile To;
+ };
+ template
+ struct __copy_cv_ {
+ template using apply = const volatile To;
+ };
+ template
+ using __copy_cv = meta::invoke<__copy_cv_, To>;
+
+ // CREF [meta.trans.other]/2.1
+ template
+ using __cref = std::add_lvalue_reference_t>;
+
+ // COMMON_REF [meta.trans.other]/2
+ template
+ struct __common_ref_ {
+ static_assert(std::is_reference::value, "");
+ static_assert(std::is_reference::value, "");
+ };
+
+ template
+ using __common_ref = meta::eval<__common_ref_>;
+
+ // [meta.trans.other]/2.5
+ template
+ using __lref_res = __cond_res<
+ __copy_cv &,
+ __copy_cv &
+ >;
+
+ // [meta.trans.other]/2.6
+ template>
+ using __rref_res = std::remove_reference_t&&;
+
+ template
+ struct __common_ref_,
+ meta::when>::value>> > {
+ using type = __lref_res;
+ };
+
+ template
+ struct __common_ref_,
+ meta::when>>,
+ meta::when>>> > {
+ using type = __rref_res;
+ };
+
+ // [meta.trans.other]/2.7
+ template
+ struct __common_ref_,
+ meta::when>>> > {
+ using type = __common_ref;
+ };
+
+ // [meta.trans.other]/2.8
+ template
+ struct __common_ref_,
+ meta::when>>> > {
+ using type = __common_ref;
+ };
+
+ template
+ struct __xref {
+ template using apply = U;
+ };
+ template
+ struct __xref {
+ template using apply = const U;
+ };
+ template
+ struct __xref {
+ template using apply = volatile U;
+ };
+ template
+ struct __xref {
+ template using apply = const volatile U;
+ };
+ template
+ struct __xref {
+ template using apply =
+ std::add_lvalue_reference_t, U>>;
+ };
+ template
+ struct __xref {
+ template using apply =
+ std::add_rvalue_reference_t, U>>;
+ };
+
+ template class,
+ template class
+ >
+ struct basic_common_reference { };
+
+ template
+ using __basic_common_reference_t = meta::eval<
+ basic_common_reference<
+ remove_cvref_t,
+ remove_cvref_t,
+ __xref::template apply,
+ __xref::template apply
+ >
+ >;
+
+ template
+ struct common_reference {};
+
+ template
+ using common_reference_t = meta::eval<
+ common_reference
+ >;
+
+ // [meta.trans.other]/5.2
+ template
+ struct common_reference {
+ using type = T;
+ };
+
+ // [meta.trans.other]/5.3.4
+ template
+ struct __common_reference3
+ : std::common_type {};
+
+ // [meta.trans.other]/5.3.3
+ template
+ struct __common_reference3>> {
+ using type = __cond_res;
+ };
+
+ template
+ struct __common_reference2
+ : __common_reference3 {};
+
+ // [meta.trans.other]/5.3.2
+ template
+ struct __common_reference2>> {
+ using type = __basic_common_reference_t;
+ };
+
+ template
+ struct __common_reference
+ : __common_reference2 { };
+
+ template
+ struct __common_reference::value && std::is_reference::value>> {
+ using type = __common_ref;
+ };
+
+ template
+ struct common_reference : __common_reference { };
+
+ // [meta.trans.other]/5.4
+ template
+ //requires requires { typename common_reference_t; }
+ struct common_reference
+ : common_reference <
+ common_reference_t, V, W...
+ > {};
+ }
+
+ template
+ using common_reference = common_impl::common_reference;
+
+ template
+ using common_reference_t = meta::eval<
+ common_reference
+ >;
+
+ //! @}
+
+
+ //FIXME: CommonReference needs better implementation
+ template
+ _utlConcept CommonReference =
+ Same, common_reference_t> &&
+ ConvertibleTo> &&
+ ConvertibleTo>;
+
+
+ // != std::Common on CommonReference
+ template
+ _utlConcept Common =
+ #if CXX_CONCEPTS
+ Same, std::common_type_t> &&
+ requires {
+ static_cast>(std::declval());
+ static_cast>(std::declval());
+ };
+// } &&
+// CommonReference<
+// std::add_lvalue_reference_t,
+// std::add_lvalue_reference_t> &&
+// CommonReference<
+// std::add_lvalue_reference_t>,
+// std::common_reference_t<
+// std::add_lvalue_reference_t,
+// std::add_lvalue_reference_t
+// >
+// >;
+ #else
+// meta::and_ <
+ Same, std::common_type_t>; //>
+// meta::bool_,
+// std::add_lvalue_reference_t
+// >>,
+// meta::bool_< CommonReference<
+// std::add_lvalue_reference_t>,
+// common_reference_t<
+// std::add_lvalue_reference_t,
+// std::add_lvalue_reference_t
+// >
+// >>
+// >::value;
+ #endif
+
+ /*!
+ * Integral
+ */
+ template
+ _utlConcept Integral = std::is_integral::value;
+
+ /*!
+ * Signed Integral
+ */
+ template
+ _utlConcept SignedIntegral = Integral && std::is_signed::value;
+
+ /*!
+ * Unsigned Integral
+ */
+ template
+ _utlConcept UnsignedIntegral = Integral && !std::is_signed::value;
+
+
+ template
+ _utlConcept MoveAssignable = std::is_move_assignable::value;
+
+ template
+ _utlConcept CopyAssignable = std::is_copy_assignable::value;
+
+ /*!
+ * Assignable
+ * \note != std:: on CommonReference
+ */
+ template
+ _utlConcept Assignable =
+ #if CXX_CONCEPTS
+ std::is_lvalue_reference::value &&
+// CommonReference<
+// const std::remove_reference_t&,
+// const std::remove_reference_t&> &&
+ requires(LHS lhs, RHS&& rhs) {
+ lhs = std::forward(rhs);
+ requires Same<
+ decltype(lhs = std::forward(rhs)), LHS
+ >;
+ };
+ #else
+ std::is_assignable::value;
+ #endif
+
+ /*!
+ * Swappable, SwappableWith
+ */
+ //! @{
+ #if CXX_VER < CXX_VER_STD_17
+ namespace swappable_with_impl {
+ struct is_swappable_with_ {
+ // can apply std::swap
+ template(), std::declval<_Up&>())),
+ typename
+ = decltype(std::swap(std::declval<_Up&>(), std::declval<_Tp&>()))>
+ static meta::true_ check(int);
+ // can not apply std::swap
+ template static meta::false_ check(...);
+ };
+ }
+ template
+ struct is_swappable_with
+ : swappable_with_impl::is_swappable_with_ {
+ using type = decltype(check<_Tp, _Up>(0));
+ };
+ #else
+ using is_swappable = std::is_swappable;
+ using is_swappable_with = std::is_swappable_with;
+ #endif
+
+ // != std:: on CommonReference
+ template
+ _utlConcept SwappableWith =
+ is_swappable_with::type::value &&
+ is_swappable_with::type::value &&
+ is_swappable_with::type::value &&
+ is_swappable_with::type::value;
+// std::CommonReference<
+// const std::remove_reference_t&,
+// const std::remove_reference_t&
+// >;
+
+ // != std:: we use is_swappable_with now is_swappable
+ template
+ _utlConcept Swappable = is_swappable_with::type::value;
+ //! @}
+
+ /*!
+ * Destructible
+ */
+ template
+ _utlConcept Destructible = std::is_nothrow_destructible::value;
+
+ /*!
+ * Constructible
+ */
+ template
+ _utlConcept Constructible =
+ Destructible && std::is_constructible::value;
+ /*!
+ * DefaultConstructible
+ */
+ template
+ _utlConcept DefaultConstructible = Constructible;
+
+ /*!
+ * MoveConstructible
+ * \note
+ * Another approach would be std::is_move_constructible::value;
+ */
+ template
+ _utlConcept MoveConstructible =
+ Constructible && ConvertibleTo;
+
+ /*!
+ * CopyConstructible
+ */
+ template
+ _utlConcept CopyConstructible =
+ MoveConstructible &&
+ Constructible> && ConvertibleTo<_ref_t, T> &&
+ Constructible> && ConvertibleTo, T> &&
+ Constructible && ConvertibleTo;
+
+ /*!
+ * Movable
+ */
+ template
+ _utlConcept Movable =
+ std::is_object::value &&
+ MoveConstructible &&
+ Assignable<_ref_t, T> &&
+ Swappable;
+
+
+ /*!
+ * Copyable
+ */
+ template
+ _utlConcept Copyable =
+ CopyConstructible &&
+ Movable &&
+ Assignable<_ref_t, const _ref_t>;
+
+
+ /*!
+ * Boolean
+ */
+ #if CXX_CONCEPTS
+ template
+ _utlConcept Boolean =
+ Movable> &&
+ requires(const std::remove_reference_t& b1,
+ const std::remove_reference_t& b2, const bool a) {
+ requires ConvertibleTo&, bool>;
+ !b1; requires ConvertibleTo;
+ b1 && a; requires Same;
+ b1 || a; requires Same;
+ b1 && b2; requires Same;
+ a && b2; requires Same;
+ b1 || b2; requires Same;
+ a || b2; requires Same;
+ b1 == b2; requires ConvertibleTo;
+ b1 == a; requires ConvertibleTo;
+ a == b2; requires ConvertibleTo;
+ b1 != b2; requires ConvertibleTo;
+ b1 != a; requires ConvertibleTo;
+ a != b2; requires ConvertibleTo;
+ };
+ #else
+ namespace details {
+ template
+ struct is_boolean_ {
+ using type = meta::false_;
+ };
+
+ template
+ struct is_boolean_ >())>,
+ meta::use_if_same_t>() == std::declval