Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7050f28bf | ||
|
|
5baa9d810d | ||
|
|
6f30abde8f | ||
|
|
dad8a7c7f5 |
@@ -397,7 +397,7 @@ INLINE_GROUPED_CLASSES = NO
|
||||
# Man pages) or section (for LaTeX and RTF).
|
||||
# The default value is: NO.
|
||||
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
INLINE_SIMPLE_STRUCTS = YES
|
||||
|
||||
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
|
||||
# enum is documented as struct, union, or enum with the name of the typedef. So
|
||||
@@ -570,7 +570,7 @@ INLINE_INFO = YES
|
||||
# name. If set to NO, the members will appear in declaration order.
|
||||
# The default value is: YES.
|
||||
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_MEMBER_DOCS = YES
|
||||
|
||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
|
||||
# descriptions of file, namespace and class members alphabetically by member
|
||||
@@ -607,7 +607,7 @@ SORT_GROUP_NAMES = NO
|
||||
# list.
|
||||
# The default value is: NO.
|
||||
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
SORT_BY_SCOPE_NAME = YES
|
||||
|
||||
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
|
||||
# type resolution of all parameters of a function it will reject a match between
|
||||
@@ -873,11 +873,7 @@ RECURSIVE = YES
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = test \
|
||||
include/utl/dev \
|
||||
include/utl/concepts \
|
||||
include/utl/com \
|
||||
include/utl/container
|
||||
EXCLUDE = test
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@@ -1091,7 +1087,7 @@ CLANG_ASSISTED_PARSING = YES
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS = -std=c++14
|
||||
CLANG_OPTIONS = -I../include
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*
|
||||
*/
|
||||
#ifndef __utl_concepts_concepts_h__
|
||||
#define __utl_concepts_concepts_h__
|
||||
#define __utl_consepts_concepts_h__
|
||||
|
||||
#include <utl/core/impl.h>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace utl {
|
||||
template <typename _T1, typename _T2, typename _Ret =_T1>
|
||||
using use_if_same_t = meta::eval<
|
||||
meta::enable_if<
|
||||
meta::same<_T1, _T2>::value, _Ret
|
||||
meta::same_<_T1, _T2>::value, _Ret
|
||||
>
|
||||
>;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace utl {
|
||||
* Same
|
||||
*/
|
||||
template <class T, class U>
|
||||
_utlConcept Same = meta::same<T, U>::value;
|
||||
_utlConcept Same = meta::same_<T, U>::value;
|
||||
|
||||
// template<class T>
|
||||
// _utlConcept Decayed = Same<T, std::decay_t<T>>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* \file utl/core/crtp.h
|
||||
* \file utl/impl/crtp.h
|
||||
* \brief CRTP idiom support header
|
||||
*/
|
||||
#ifndef __utl_impl_crtp_h__
|
||||
@@ -13,10 +13,8 @@
|
||||
*
|
||||
* utl supports both CRTP idiom and dynamic polymorphism. By default
|
||||
* CRTP is the preferred way. If the user need virtuals then instead of
|
||||
* CRTP type, the \c virtual_tag can passed to base class. The rest
|
||||
* CRTP type, the \ref virtual_tag can passed to base class. The rest
|
||||
* will handled by utl automatically.
|
||||
*
|
||||
* \sa utl::virtual_tag
|
||||
*/
|
||||
//!@{
|
||||
namespace utl {
|
||||
@@ -27,8 +25,8 @@ namespace utl {
|
||||
|
||||
//! \def CRTP boilerplate lines
|
||||
#define _CRTP_IMPL(T) \
|
||||
constexpr T& impl() { return *static_cast<T*>(this); } \
|
||||
constexpr const T& impl() const { return *static_cast<const T*>(this); }
|
||||
constexpr T& impl() { return *static_cast<T*>(this); } \
|
||||
constexpr const T& impl() const { return *static_cast<const T*>(this); }
|
||||
|
||||
}
|
||||
//!@}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//!
|
||||
//! This can be used in the user files to check for uTL versions.
|
||||
//! The version number is constructed using:\n
|
||||
//! \f$ ver = (Maj*10000 + Min*100 + Patch) \f$
|
||||
//! ver = (Maj*10000 + Min*100 + Patch)
|
||||
#define UTL_VERSION_VALUE ( (UTL_VERSION_MAJOR * 10000) \
|
||||
+ (UTL_VERSION_MINOR * 100) \
|
||||
+ UTL_VERSION_PATCH)
|
||||
|
||||
@@ -398,7 +398,7 @@ namespace utl {
|
||||
typename T::difference_type;
|
||||
typename T::pointer;
|
||||
typename T::reference;
|
||||
requires same<
|
||||
requires same_<
|
||||
typename T::iterator_category,
|
||||
std::output_iterator_tag
|
||||
>::value;
|
||||
@@ -675,7 +675,7 @@ namespace utl {
|
||||
typename T::difference_type;
|
||||
typename T::pointer;
|
||||
typename T::reference;
|
||||
requires same <
|
||||
requires same_ <
|
||||
typename T::iterator_category,
|
||||
std::input_iterator_tag
|
||||
>::value;
|
||||
@@ -960,7 +960,7 @@ namespace utl {
|
||||
typename T::difference_type;
|
||||
typename T::pointer;
|
||||
typename T::reference;
|
||||
requires same<
|
||||
requires same_<
|
||||
typename T::iterator_category,
|
||||
std::input_iterator_tag
|
||||
>::value;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace utl {
|
||||
namespace meta {
|
||||
|
||||
/*!
|
||||
* \brief meta's empty type
|
||||
* 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
|
||||
@@ -292,13 +292,13 @@ namespace meta{
|
||||
//! \name same
|
||||
//! @{
|
||||
template<typename T1, typename T2>
|
||||
struct same : false_ { };
|
||||
struct same_ : false_ { };
|
||||
|
||||
template<typename Tp>
|
||||
struct same <Tp, Tp> : true_ { };
|
||||
struct same_ <Tp, Tp> : true_ { };
|
||||
|
||||
template<typename T1, typename T2>
|
||||
using not_same = not_<eval<same<T1, T2>>>;
|
||||
using not_same_ = not_<eval<same_<T1, T2>>>;
|
||||
//! @}
|
||||
|
||||
//! @}
|
||||
|
||||
@@ -40,10 +40,8 @@ namespace meta {
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Not a type to use in detected idiom.
|
||||
*
|
||||
* This type can not be constructed, destructed or copied.
|
||||
* Not a type to use in detected idiom. This type can
|
||||
* not be constructed, destructed or copied.
|
||||
*/
|
||||
struct nat_ {
|
||||
nat_() = delete;
|
||||
@@ -179,7 +177,7 @@ namespace meta {
|
||||
template <typename Expected,
|
||||
template<typename...> class Op, typename... Args >
|
||||
using is_detected_exact = eval <
|
||||
same<Expected, detected_t<Op, Args...>>
|
||||
same_<Expected, detected_t<Op, Args...>>
|
||||
>;
|
||||
|
||||
//! evaluates to true if evaluation of Op<Args...> is \p Expected and to false if not
|
||||
|
||||
+34
-115
@@ -11,7 +11,7 @@
|
||||
|
||||
/*!
|
||||
* \ingroup meta
|
||||
* \defgroup meta_invoke Invoke
|
||||
* \defgroup invoke Invoke
|
||||
* A meta-programming invoke() analogous.
|
||||
*
|
||||
* This module provides <b>higher order</b> tools to meta. utl::meta's metafunctions inputs are types.
|
||||
@@ -39,22 +39,22 @@ namespace meta{
|
||||
//! @{
|
||||
|
||||
//! Identity is a metafunction always return the input type
|
||||
template <typename Tp>
|
||||
template <typename _Tp>
|
||||
struct identity {
|
||||
#if defined (UTL_WORKAROUND_CWG_1558)
|
||||
// redirect unused Ts... via void_t
|
||||
template <typename... Ts>
|
||||
using apply = first_of<Tp, void_t<Ts...>>; //!< identity is invokable, must also have apply
|
||||
using apply = first_of<_Tp, void_t<Ts...>>; //!< identity is invokable, must also have apply
|
||||
#else
|
||||
template <typename...>
|
||||
using apply = Tp; //!< identity is invokable, must also have apply
|
||||
using apply = _Tp; //!< identity is invokable, must also have apply
|
||||
#endif
|
||||
using type = Tp; //!< identity
|
||||
using type = _Tp; //!< identity
|
||||
};
|
||||
|
||||
//! identity type alias
|
||||
template <typename Tp>
|
||||
using identity_t = eval<identity<Tp>>;
|
||||
template <typename _Tp>
|
||||
using identity_t = eval<identity<_Tp>>;
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
@@ -79,17 +79,11 @@ namespace meta{
|
||||
|
||||
//! \name wrap
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Wraps an n-ary Metafunction \c F to a Metafunction Class
|
||||
*
|
||||
* wrap is a higher-order primitive that wraps an n-ary Metafunction
|
||||
* to create a corresponding Metafunction Class (Invocable). This way
|
||||
* we can pass Metafunctions as types to other metafunctions and let
|
||||
* them \c invoke the inner templated apply.
|
||||
*
|
||||
* \tparam F The metafunction to wrap
|
||||
* them \c invoke the inner templated apply
|
||||
*/
|
||||
template <template <typename...> class F>
|
||||
struct wrap {
|
||||
@@ -97,19 +91,7 @@ namespace meta{
|
||||
using apply = F<Args...>;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Wraps an n-ary Metafunction \c F taking literal constants of type \c T
|
||||
* to a Metafunction Class
|
||||
*
|
||||
* wrap_i is a higher-order primitive that wraps an n-ary Metafunction
|
||||
* to create a corresponding Metafunction Class (Invocable).
|
||||
* This way we can pass Metafunctions as types to other metafunctions and let
|
||||
* them \c invoke the inner templated apply.
|
||||
*
|
||||
* \tparam T Type of integral constants
|
||||
* \tparam F The metafunction to wrap
|
||||
*/
|
||||
//! Wrap a template \p F taking literal constants of type \p T into an Invokable
|
||||
template <typename T, template <T...> class F>
|
||||
struct wrap_i {
|
||||
// requires meta::Integral
|
||||
@@ -140,7 +122,7 @@ namespace meta{
|
||||
static nil_ check (...); //< all other combinations
|
||||
|
||||
using type = if_ <
|
||||
not_same<
|
||||
not_same_<
|
||||
nil_,
|
||||
decltype(check<F>(0))
|
||||
>, true_, false_
|
||||
@@ -163,41 +145,18 @@ namespace meta{
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Check if we can instantiate metafunction \c F with parameters \p Ts
|
||||
*
|
||||
* \tparam F The metafunction
|
||||
* \tparam Ts The parameters to \c F
|
||||
*/
|
||||
template<template<typename...> class F, typename... Ts>
|
||||
//! check if we can instantiate \p F with parameters \p T
|
||||
template<template<typename...> class F, typename... T>
|
||||
using is_applicable_t = eval<
|
||||
details::is_applicable_<F, Ts...>
|
||||
details::is_applicable_<F, T...>
|
||||
>;
|
||||
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Check if we can invoke the quoted metafunction \c Q with parameters \p Ts
|
||||
*
|
||||
* \tparam Q The quoted metafunction
|
||||
* \tparam Ts The parameters to \c Q
|
||||
*
|
||||
* \sa utl::meta::quote
|
||||
*/
|
||||
template<typename Q, typename... Ts>
|
||||
//! check if we can invoke \p Q with parameters \p T
|
||||
template<typename Q, typename... T>
|
||||
using is_applicable_qt = eval <
|
||||
details::is_applicable_q_ <Q, Ts...>
|
||||
details::is_applicable_q_ <Q, T...>
|
||||
>;
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Check if we can instantiate metafunction \c F with parameters \p Is of type \c T
|
||||
*
|
||||
* \tparam T The type of \c Is
|
||||
* \tparam F The metafunction
|
||||
* \tparam Is The parameters to \c F
|
||||
*/
|
||||
//! check if we can instantiate \p F with parameters \p Is of type \p T
|
||||
template <typename T, template<T...> class F, T... Is>
|
||||
using is_applicable_it = eval<
|
||||
details::is_applicable_i_<T, F, Is...>
|
||||
@@ -223,25 +182,16 @@ namespace meta{
|
||||
//! template<template<typename...> class F, typename... Ts>
|
||||
//! using defer_ = F<Ts...>;
|
||||
//!
|
||||
//! The use of struct here is due to Core issue 1430 [1] and is used
|
||||
//! as suggested by Roy Crihfield in [2].
|
||||
//! The use of struct here is due to Core issue 1430 \ref link1 and is used
|
||||
//! as suggested by Roy Crihfield in \ref link2.
|
||||
//! In short, this is due to language's inability to expand Ts... into
|
||||
//! a fixed parameter list of an alias template.
|
||||
//!
|
||||
//! [1] https://wg21.link/cwg1430\n
|
||||
//! [2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498
|
||||
//! \anchor link1 https://wg21.link/cwg1430
|
||||
//! \anchor link2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Postpone the instantiation of a metafunction \c F with parameters \c Ts
|
||||
*
|
||||
* This metafunction first checks if the given arguments \c Ts are applicable to
|
||||
* the metafunction \c F and if so nest inside (a layer deeper) the <em>metafunction call</em>.
|
||||
*
|
||||
* \tparam F The metafunction
|
||||
* \tparam Ts The parameters (arguments) to \c F
|
||||
*/
|
||||
//! defer alias template for F<Ts...>
|
||||
template<template<class...> class F, class... Ts>
|
||||
using defer = if_<
|
||||
details::is_applicable_<F, Ts...>,
|
||||
@@ -249,17 +199,7 @@ namespace meta{
|
||||
nil_ //!< Safe, nil_ is dereferencable
|
||||
>;
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Postpone the instantiation of a metafunction \c F with parameters \c Is of type \c T.
|
||||
*
|
||||
* This metafunction first checks if the given arguments \c Is of type \c T are applicable to
|
||||
* the metafunction \c F and if so nest inside (a layer deeper) the <em>metafunction call</em>.
|
||||
*
|
||||
* \tparam T The type of parameters
|
||||
* \tparam F The metafunction
|
||||
* \tparam Is The parameters (arguments) to \c F
|
||||
*/
|
||||
//! defer_i alias template for F<T, Is...>
|
||||
template <typename T, template<T...> class F, T... Is>
|
||||
using defer_i = if_ <
|
||||
details::is_applicable_i_<T, F, Is...>,
|
||||
@@ -271,16 +211,11 @@ namespace meta{
|
||||
//! \name quote
|
||||
//! @{
|
||||
/*!
|
||||
* \brief
|
||||
* Wraps an n-ary Metafunction \c F to a Metafunction Class using meta::defer<>
|
||||
*
|
||||
* quote is a higher-order primitive that wraps an n-ary Metafunction
|
||||
* quote deferred is a higher-order primitive that wraps an n-ary Metafunction
|
||||
* to create a corresponding Metafunction Class (Invocable) using defer<> to
|
||||
* postpone the evaluation of Metafunction. This is a safe version of \c wrap<>.\n
|
||||
* postpone the evaluation of Metafunction. This is a safe version of \c wrap<>.
|
||||
* Again this way we can pass Metafunctions as types to other metafunctions and let
|
||||
* them \c invoke the inner templated apply
|
||||
*
|
||||
* \tparam F The metafunction to wrap
|
||||
*/
|
||||
template <template <typename...> class F>
|
||||
struct quote {
|
||||
@@ -290,21 +225,7 @@ namespace meta{
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Wraps an n-ary Metafunction \c F taking literal constants of type \c T
|
||||
* to a Metafunction Class using meta::defer<>
|
||||
*
|
||||
* quote is a higher-order primitive that wraps an n-ary Metafunction
|
||||
* to create a corresponding Metafunction Class (Invocable) using defer<> to
|
||||
* postpone the evaluation of Metafunction. This is a safe version of \c wrap<>.\n
|
||||
* Again this way we can pass Metafunctions as types to other metafunctions and let
|
||||
* them \c invoke the inner templated apply
|
||||
*
|
||||
* \tparam T Type of integral constants
|
||||
* \tparam F The metafunction to wrap
|
||||
*/
|
||||
//! Wrap a template \p F taking literal constants of type \p T into an Invokable
|
||||
template <typename T, template <T...> class F>
|
||||
struct quote_i {
|
||||
// requires meta::Integral
|
||||
@@ -358,8 +279,7 @@ namespace meta{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Create an invocable from other invocables(quoted metafunctions) by composition.
|
||||
* Create an invocable from other invocables(quoted metafunctions) by composition.
|
||||
* \note
|
||||
* This implies from N invocables in \p Fns the first N-1 has to be unary.
|
||||
* Thats because of the "return" type of metafunction. They can only return one
|
||||
@@ -375,8 +295,7 @@ namespace meta{
|
||||
using compose = details::compose_<Fns...>;
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Create an invocable from other metafunctions by composition.
|
||||
* Create an invocable from other metafunctions by composition.
|
||||
* \note
|
||||
* This implies from N invocables in \p Fns the first N-1 has to be unary.
|
||||
* Thats because of the "return" type of metafunction. They can only return one
|
||||
@@ -393,8 +312,8 @@ namespace meta{
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Applies the invocable \p Fn by binding the arguments \p Ts to the front of \p Fn.
|
||||
* Applies the invocable \p Fn by binding the arguments \p Ts
|
||||
* to the front of \p Fn.
|
||||
*/
|
||||
template<typename Fn, typename... Ts>
|
||||
struct bind_front {
|
||||
@@ -403,8 +322,8 @@ namespace meta{
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Applies the Invocable \p Fn by binding the arguments \p Ts to the back of \p Fn.
|
||||
* Applies the Invocable \p Fn by binding the arguments \p Ts
|
||||
* to the back of \p Fn.
|
||||
*/
|
||||
template<typename Fn, typename... Ts>
|
||||
struct bind_back {
|
||||
@@ -419,13 +338,13 @@ namespace meta{
|
||||
template <typename T1>
|
||||
struct same_as {
|
||||
template <typename T2>
|
||||
struct apply : same<T1, T2> { };
|
||||
struct apply : same_<T1, T2> { };
|
||||
};
|
||||
|
||||
template <typename T1>
|
||||
struct not_same_as {
|
||||
template <typename T2>
|
||||
struct apply : not_same<T1, T2> { };
|
||||
struct apply : not_same_<T1, T2> { };
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
+7
-12
@@ -10,27 +10,22 @@
|
||||
*
|
||||
* uTL::meta is a simple metaprogramming library used widely inside uTL.
|
||||
* The lib is provided to the end user via namespace \c utl::meta
|
||||
* The library assembles:
|
||||
* The library consist of:
|
||||
*
|
||||
* - integral constant based, operation and arithmetic functionality\n
|
||||
* meta defines wrappers for all of integral types such as \c int, \c long, \c char, \c uint32_t etc...
|
||||
* and also facilities to emulate:
|
||||
* 1. <b>conditional (if)</b>
|
||||
* 2. <b>logical operations</b> like \c or, \c and, \c not, \c bitor, \c bitand etc...
|
||||
* 3. <b>math operations</b> like \c add, \c sub, \c modulo
|
||||
* 4. <b>comparison operations</b> like \c equal, \c not_equal etc...
|
||||
*
|
||||
* 1. <b>conditional (if)</b>
|
||||
* 2. <b>logical operations</b> like \c or, \c and, \c not, \c bitor, \c bitand etc...
|
||||
* 3. <b>math operations</b> like \c add, \c sub, \c modulo
|
||||
* 4. <b>comparison operations</b> like \c equal, \c not_equal etc...
|
||||
* All of these operate on integral types.
|
||||
*
|
||||
* - <b>SFINAE</b> wrappers as syntactic sugar to the rest of the uTL.
|
||||
*
|
||||
* - Walter's Brown <b>detection idiom</b> to help uTL concept implementation.
|
||||
*
|
||||
* - <b>Higher order</b> metafunction tools for composition.\n
|
||||
* This module provides tools such as \c wrap, \c compose, \c fold, \c bind etc... The user can
|
||||
* wrap metafunctions as types and pass them around to other metafunctions. The evaluation
|
||||
* of these functions can be done both in aggressive or lazy maner using tools such as \c eval or \c invoke
|
||||
*
|
||||
* wrap metafunctions as types and pass them around other metafunctions. The evaluation
|
||||
* of these functions can be done both aggressive or lazy using tools such as \c eval or \c invoke
|
||||
* - <b>typelist "container"</b> implementation.\n
|
||||
* Typelist is a container like template type holding the parameter list as items in the container.
|
||||
* This facility has also all the expected eco-system of functions like \c push_front,
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#define __utl_meta_sfinae_h__
|
||||
|
||||
#include <utl/core/impl.h>
|
||||
#include <utl/meta/basic.h>
|
||||
#include <type_traits>
|
||||
|
||||
/*!
|
||||
@@ -54,12 +53,12 @@ namespace meta {
|
||||
//! If same type resolves to _Ret, else SFINAE
|
||||
template <typename _T1, typename _T2, typename _Ret =_T1>
|
||||
using use_if_same_t = enable_if_t<
|
||||
same<_T1, _T2>::value, _Ret
|
||||
same_<_T1, _T2>::value, _Ret
|
||||
>;
|
||||
//! If not same type resolves to _Ret, else SFINAE
|
||||
template <typename _T1, typename _T2, typename _Ret =_T1>
|
||||
using use_if_not_same_t = enable_if_t<
|
||||
!same<_T1, _T2>::value, _Ret
|
||||
!same_<_T1, _T2>::value, _Ret
|
||||
>;
|
||||
//! If any type (_T1 or _T2) type resolves to _Ret, else to SFINAE
|
||||
template <typename T1, typename... Ts>
|
||||
|
||||
+39
-55
@@ -13,30 +13,6 @@
|
||||
/*!
|
||||
* \ingroup meta
|
||||
* \defgroup typelist typelist
|
||||
*
|
||||
* 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 an object, not a subject.
|
||||
* This way the name gives the feeling of a container and smells like Python.\n
|
||||
*
|
||||
* 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).\n
|
||||
*
|
||||
* \code{.cpp}
|
||||
* using l1 = typelist<int, void*, double, void>;
|
||||
* l1 a {};
|
||||
* \endcode
|
||||
*
|
||||
* boost::hana [3] suggests 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 comes along).\n
|
||||
* 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/ \n
|
||||
* [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html \n
|
||||
* [3]: https://github.com/boostorg/hana \n
|
||||
*/
|
||||
//! @{
|
||||
|
||||
@@ -45,8 +21,31 @@ namespace meta {
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* The \c typelist 's implementation container
|
||||
* \tparam Ts The \a contained types
|
||||
* 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 an object, not a subject.
|
||||
* This way the name gives the feeling of a container and smells like Python.\n
|
||||
*
|
||||
* 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).\n
|
||||
*
|
||||
* \code{.cpp}
|
||||
* using l1 = typelist<int, void*, double, void>;
|
||||
* l1 a {};
|
||||
* \endcode
|
||||
*
|
||||
* boost::hana [3] suggests 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 comes along).\n
|
||||
* 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/ \n
|
||||
* [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html \n
|
||||
* [3]: https://github.com/boostorg/hana \n
|
||||
*/
|
||||
template <typename... Ts>
|
||||
struct typelist {
|
||||
@@ -158,12 +157,12 @@ namespace meta {
|
||||
template <typename Fn, typename Seq>
|
||||
struct apply_ { };
|
||||
|
||||
// Sequence == typelist<>
|
||||
//! \c Sequence == typelist<>
|
||||
template<typename Fn, typename ...List>
|
||||
struct apply_<Fn, typelist<List...>> {
|
||||
using type = invoke<Fn, List...>;
|
||||
};
|
||||
// Sequence == integer_sequence<>
|
||||
//! Sequence == integer_sequence<>
|
||||
template <typename Fn, typename T, T... Is>
|
||||
struct apply_<Fn, integer_sequence<T, Is...>> {
|
||||
using type = invoke<Fn, integral_<T, Is>...>;
|
||||
@@ -171,13 +170,14 @@ namespace meta {
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Apply the Invocable \c Fn using the types in the type \c Seq as arguments.
|
||||
* Apply the Invocable \c Fn using the types in the type \c Seq as arguments.
|
||||
* \note
|
||||
* This is the opposed operation of typelist<Ts...>
|
||||
* This is the opposed operation of typelist<Ts...>
|
||||
*
|
||||
* If \c Seq == typelist<> then unpack typelist and apply to \c Fn \n
|
||||
* It \c Seq == integer_sequence<> then unpack and use the integral_c<> of each integer
|
||||
* If \c Seq == typelist<> then
|
||||
* Unpack typelist and apply to \c Fn
|
||||
* It \c Seq == integer_sequence<> then
|
||||
* Unpack and use the integral_c<> of each integer
|
||||
*/
|
||||
template <typename Fn, typename Seq>
|
||||
using apply = apply_impl::apply_<Fn, Seq>;
|
||||
@@ -244,7 +244,7 @@ namespace meta {
|
||||
//! @{
|
||||
namespace front_impl {
|
||||
template <typename L>
|
||||
struct front_ { using type = nil_; };
|
||||
struct front_ { };
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
struct front_<typelist<Head, Tail...>> {
|
||||
@@ -265,7 +265,7 @@ namespace meta {
|
||||
//! @{
|
||||
namespace back_impl {
|
||||
template <typename List>
|
||||
struct back_ { using type = nil_; };
|
||||
struct back_ { };
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
struct back_<typelist<Head, Tail...>> {
|
||||
@@ -636,7 +636,7 @@ namespace meta {
|
||||
|
||||
/*!
|
||||
* Search for the first \c Item on the \c List for which the predicate \c Pred
|
||||
* yields to \c true_ when `eval<invoke<Pred, Item>>`
|
||||
* returns true_ when `eval<invoke<Pred, Item>>`
|
||||
*
|
||||
* Complexity \f$ O(N) \f$
|
||||
*
|
||||
@@ -684,7 +684,7 @@ namespace meta {
|
||||
|
||||
/*!
|
||||
* Search for the first \c Item on the \c List for which the predicate \c Pred
|
||||
* yields to \c true_ when `eval<invoke<Pred, Item>>` and return the rest of the \c List
|
||||
* returns true_ when `eval<invoke<Pred, Item>>` and return the rest of the \c List
|
||||
* starting from that position as new typelist
|
||||
*
|
||||
* Complexity \f$ O(N) \f$
|
||||
@@ -705,22 +705,6 @@ namespace meta {
|
||||
using seek = seek_if <List, same_as<T>>;
|
||||
//! @}
|
||||
|
||||
//! \name first_if
|
||||
//! @{
|
||||
/*!
|
||||
* Search and returns the first \c Item on the \c List for which the predicate \c Pred
|
||||
* yields to true_ when \code eval<invoke<Pred, Item>> \endcode
|
||||
*
|
||||
* Complexity \f$ O(N) \f$
|
||||
*
|
||||
* \tparam List A typelist
|
||||
* \tparam Pred A Unary invocable predicate
|
||||
* \return On success the item, otherwise utl::meta::nil_
|
||||
*/
|
||||
template <typename List, typename Pred>
|
||||
using first_if = front<seek_if<List, Pred>>;
|
||||
//! @}
|
||||
|
||||
//! \name count_if
|
||||
//! @{
|
||||
namespace count_if_impl {
|
||||
@@ -796,8 +780,8 @@ namespace meta {
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns a new typelist with elements, the elements of \c List that satisfy the
|
||||
* invocable \c Pred such that `eval<invoke<Pred, Item>>` yields to \c true_
|
||||
* Return a new typelist with elements, the elements of \c List that satisfy the
|
||||
* invocable \c Pred such that `eval<invoke<Pred, Item>>` is \c true_
|
||||
*
|
||||
* Complexity \f$ O(N) \f$
|
||||
*
|
||||
|
||||
@@ -12,16 +12,13 @@
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
//! \defgroup utility Utility
|
||||
|
||||
/*!
|
||||
* \ingroup utility
|
||||
* \defgroup util_invoke Invoke
|
||||
* \defgroup invoke Invoke
|
||||
*/
|
||||
//! @{
|
||||
namespace utl {
|
||||
|
||||
//#if !defined __cpp_lib_is_invocable
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
@@ -104,41 +101,16 @@ namespace utl {
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//! Invoke the Callable object \c fn with the parameters args.
|
||||
//! As by INVOKE(std::forward<F>(f), std::forward<Args>(args)...).
|
||||
//!
|
||||
//! \note
|
||||
//! This implementation fills the lack of an invoke() utility for builds
|
||||
//! pre-c++17.
|
||||
//!
|
||||
//! \param fn Callable object to be invoked
|
||||
//! \param args Arguments to pass to \c fn
|
||||
//! \return The return of the Callable underling functionality
|
||||
//!
|
||||
template<typename Callable, typename... Args>
|
||||
inline decltype(auto) invoke(Callable&& fn, Args&&... args) {
|
||||
//! Invoke a callable object (for C++14)
|
||||
template<typename _Callable, typename... _Args>
|
||||
inline decltype(auto) invoke(_Callable&& fn, _Args&&... args) {
|
||||
return detail::invoke_impl_(
|
||||
std::forward<Callable>(fn), std::forward<Args>(args)...
|
||||
std::forward<_Callable>(fn), std::forward<_Args>(args)...
|
||||
);
|
||||
}
|
||||
//! @}
|
||||
|
||||
//!
|
||||
//! \brief
|
||||
//! Determines whether \c F can be invoked with the arguments \c Args....
|
||||
//!
|
||||
//! Formally, determines whether invoke(declval<Fn>(), declval<ArgTypes>()...)
|
||||
//! is well formed when treated as an unevaluated operand,
|
||||
//! where invoke is \c Callable.
|
||||
//!
|
||||
//! \note
|
||||
//! This implementation fills the lack of an invoke() utility for builds
|
||||
//! pre-c++17.
|
||||
//!
|
||||
//! \tparam F The candidate type to check if its invocable
|
||||
//! \tparam Args The arguments for the call
|
||||
//! \return If \c F is invocable
|
||||
//! \arg true Is invocable
|
||||
//! \arg false Is not invocable
|
||||
//! std::is_invocable trait for C++14
|
||||
template <typename F, typename... Args>
|
||||
struct is_invocable :
|
||||
std::is_constructible<
|
||||
@@ -146,19 +118,7 @@ namespace utl {
|
||||
std::reference_wrapper<typename std::remove_reference<F>::type>
|
||||
> { };
|
||||
|
||||
//! \brief
|
||||
//! Determines whether \c F can be invoked with the arguments \c Args...
|
||||
//! to yield a result that is convertible to \c R.
|
||||
//!
|
||||
//! Formally, determines whether invoke(declval<Fn>(), declval<ArgTypes>()...)
|
||||
//! is well formed when treated as an unevaluated operand, where invoke is \c Callable.
|
||||
//!
|
||||
//! \tparam R The return type of invocable functionality
|
||||
//! \tparam F The candidate type to check if its invocable
|
||||
//! \tparam Args The arguments to pass to \c F
|
||||
//! \return If \c F is invocable
|
||||
//! \arg true Is invocable
|
||||
//! \arg false Is not invocable
|
||||
//! std::is_invocable_r trait for C++14
|
||||
template <typename R, typename F, typename... Args>
|
||||
struct is_invocable_r :
|
||||
std::is_constructible<
|
||||
@@ -171,55 +131,38 @@ namespace utl {
|
||||
*/
|
||||
//! @{
|
||||
namespace detail {
|
||||
template<typename Callable, typename... Args>
|
||||
template<typename _Callable, typename... _Args>
|
||||
struct try_invoke {
|
||||
using type = decltype (
|
||||
detail::invoke_impl_(std::declval<Callable&&>(), std::declval<Args&&>()...)
|
||||
detail::invoke_impl_(std::declval<_Callable&&>(), std::declval<_Args&&>()...)
|
||||
);
|
||||
};
|
||||
|
||||
template<bool B, typename Callable, typename... Args>
|
||||
template<bool B, typename _Callable, typename... _Args>
|
||||
struct invoke_result_ {
|
||||
using type = meta::nil_;
|
||||
};
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
struct invoke_result_ <true, Callable, Args...> {
|
||||
template <typename _Callable, typename... _Args>
|
||||
struct invoke_result_ <true, _Callable, _Args...> {
|
||||
using type = meta::invoke_t<
|
||||
meta::quote<try_invoke>, Callable, Args...
|
||||
meta::quote<try_invoke>, _Callable, _Args...
|
||||
>;
|
||||
};
|
||||
}
|
||||
//! trait that deduces the return type of an INVOKE expression at compile time.
|
||||
//!
|
||||
//! \tparam Callable The candidate type to check if its invocable
|
||||
//! \tparam Args The arguments to pass to \c F
|
||||
//!
|
||||
//! \b member \n
|
||||
//! \::type The return type of the \c Callable type if invoked with the arguments Args....
|
||||
template <typename Callable, typename... Args>
|
||||
//! invoke_result (for C++14)
|
||||
template <typename _Callable, typename... _Args>
|
||||
using invoke_result = detail::invoke_result_<
|
||||
is_invocable<Callable, Args...>::value,
|
||||
Callable,
|
||||
Args...
|
||||
is_invocable<_Callable, _Args...>::value,
|
||||
_Callable,
|
||||
_Args...
|
||||
>;
|
||||
|
||||
//! trait that deduces the return type of an INVOKE expression at compile time.
|
||||
//!
|
||||
//! \tparam Callable The candidate type to check if its invocable
|
||||
//! \tparam Args The arguments to pass to \c F
|
||||
//!
|
||||
//! \return The type of the \c Callable type if invoked with the arguments Args....
|
||||
template<typename Callable, typename... Args>
|
||||
//! invoke_result_t (for C++14)
|
||||
template<typename _Callable, typename... _Args>
|
||||
using invoke_result_t = meta::eval <
|
||||
invoke_result<Callable, Args...>
|
||||
invoke_result<_Callable, _Args...>
|
||||
>;
|
||||
//! @}
|
||||
|
||||
//#else
|
||||
//using is_invocable = std::is_invocable;
|
||||
//
|
||||
//#endif
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
+51
-104
@@ -17,55 +17,12 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# ult notes:
|
||||
# ==============
|
||||
# This makefile provides support for unix-like local builds and
|
||||
# docker based builds for gcc and clang.
|
||||
# ** msvc is not currently supported.
|
||||
#
|
||||
# Use cases:
|
||||
# 1) build localy using **local rules** in terminal.
|
||||
# example:
|
||||
# make -j4 MK_ARG="-std=c++14 -fconcepts" build-gcc
|
||||
#
|
||||
# 2) build localy using **docker based rules** via terminal or script
|
||||
# in order to compile for all compilers/versions/dialects.
|
||||
# example in bash:
|
||||
# #!/bin/bash
|
||||
# for im in gcc:8 gcc:9 gcc:10; do
|
||||
# for dial in -std=c++14 -std=c++17; do
|
||||
# make IMAGE="$im" MK_ARG="$dial" dock-gcc
|
||||
# done
|
||||
# done
|
||||
#
|
||||
# 3) build inside a docker instance using **local rules** in order to
|
||||
# build and test using a CD/CI system.
|
||||
# example in a yml file:
|
||||
# image: gcc:8
|
||||
# build:
|
||||
# stage: build
|
||||
# - make MK_ARG="-std=c++14" build-gcc
|
||||
# - make MK_ARG="-std=c++14 -fconcepts" build-gcc
|
||||
# - make MK_ARG="-std=c++17" build-gcc
|
||||
# - make MK_ARG="-std=c++17 -fconcepts" build-gcc
|
||||
# - make MK_ARG="-std=c++2a" build-gcc
|
||||
# ... etc
|
||||
# test:
|
||||
# stage: test
|
||||
# - bin/utlTest
|
||||
# ... etc
|
||||
|
||||
|
||||
# ============== Project settings ==============
|
||||
# Project's name
|
||||
PROJECT := utl
|
||||
# ========== Project settings ==========
|
||||
# Excecutable's name
|
||||
TARGET := utlTest
|
||||
# Source directories list(space seperated).
|
||||
# Relative path, under current directory only
|
||||
# Source directories list(space seperated). Full or relative path
|
||||
SRC_DIR_LIST := tests gtest
|
||||
# Include directories list(space seperated).
|
||||
# Relative path
|
||||
# Include directories list(space seperated). Full or relative path
|
||||
INC_DIR_LIST := ../include gtest
|
||||
# Exclude files list(space seperated). Filenames only.
|
||||
# EXC_FILE_LIST := bad.cpp old.cpp
|
||||
@@ -75,7 +32,7 @@ BUILD_DIR := bin
|
||||
OBJ_DIR := $(BUILD_DIR)/obj
|
||||
DEP_DIR := $(BUILD_DIR)/.dep
|
||||
|
||||
# ============== Compiler settings ==============
|
||||
# ========== Compiler settings ==========
|
||||
CLANGXX := clang++
|
||||
GCCXX := g++
|
||||
CSIZE := size
|
||||
@@ -85,35 +42,21 @@ REL_CFLAGS := -Wall -Wextra -O2
|
||||
# Pre-defines
|
||||
# PRE_DEFS := MYCAB=1729 SUPER_MODE
|
||||
|
||||
# ============== Linker settings ==============
|
||||
# ========== Linker settings ==========
|
||||
# Linker flags
|
||||
LDFLAGS := -pthread
|
||||
# Map output file
|
||||
MAP_FILE := output.map
|
||||
MAP_FLAG := -Xlinker -Map=$(BUILD_DIR)/$(MAP_FILE)
|
||||
|
||||
# ============== Docker settings ==============
|
||||
# We need:
|
||||
# 1) Bind the entire project directory(the dir that icludes all the code) as volume.
|
||||
# 2) In docker instance change to working directory(where the makefile is).
|
||||
# For utl we use the directories `${PWD%/*}` and `test`.
|
||||
# We double-$$ for double evaluating.
|
||||
DOCKER_VOL_DIR := "$${PWD%/*}"
|
||||
DOCKER_WRK_DIR := test
|
||||
DOCKER_RUN := docker run --rm -v $(DOCKER_VOL_DIR):/usr/src/$(PROJECT) -w /usr/src/$(PROJECT)/$(DOCKER_WRK_DIR)
|
||||
|
||||
# ============== Default settings ==============
|
||||
# compiler and compiler flags. By default docker is not used.
|
||||
# ========== Default settings ==========
|
||||
# compiler and compiler flagfs
|
||||
CFLAGS := $(DEB_CFLAGS)
|
||||
CXX := $(GCCXX)
|
||||
DOCKER :=
|
||||
|
||||
#
|
||||
# =========== Main body and Patterns ===========
|
||||
#
|
||||
ifeq ($(OS), Windows_NT)
|
||||
TARGET := $(TARGET).exe
|
||||
endif
|
||||
INC := $(foreach dir,$(INC_DIR_LIST),-I$(dir))
|
||||
DEF := $(foreach def,$(PRE_DEFS),-D$(def))
|
||||
EXC := $(foreach fil,$(EXC_FILE_LIST), \
|
||||
@@ -124,11 +67,10 @@ EXC := $(foreach fil,$(EXC_FILE_LIST), \
|
||||
SRC := $(wildcard *.cpp)
|
||||
SRC += $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/*.cpp))
|
||||
SRC += $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/**/*.cpp))
|
||||
#SRC := $(abspath $(filter-out $(EXC),$(SRC)))
|
||||
SRC := $(filter-out $(EXC),$(SRC))
|
||||
SRC := $(abspath $(filter-out $(EXC),$(SRC)))
|
||||
|
||||
OBJ := $(foreach file,$(SRC:%.cpp=%.o),$(OBJ_DIR)/$(file))
|
||||
DEP := $(foreach file,$(SRC:%.cpp=%.d),$(DEP_DIR)/$(file))
|
||||
OBJ := $(foreach file,$(SRC:%.cpp=%.o),$(OBJ_DIR)$(file))
|
||||
DEP := $(foreach file,$(SRC:%.cpp=%.d),$(DEP_DIR)$(file))
|
||||
|
||||
|
||||
# Make Dependencies pattern.
|
||||
@@ -138,14 +80,14 @@ DEP := $(foreach file,$(SRC:%.cpp=%.d),$(DEP_DIR)/$(file))
|
||||
# It is based on Tom Tromey's method.
|
||||
#
|
||||
# Invoke cpp to create makefile rules with dependencies for each source file
|
||||
$(DEP_DIR)/%.d: %.cpp
|
||||
$(DEP_DIR)%.d: %.cpp
|
||||
@mkdir -p $(@D)
|
||||
@$(DOCKER) $(CXX) -E $(CFLAGS) $(INC) $(DEF) -MM -MT $(OBJ_DIR)/$(<:.cpp=.o) -MF $@ $<
|
||||
@$(CXX) -E $(CFLAGS) $(INC) $(DEF) -MM -MT $(OBJ_DIR)$(<:.cpp=.o) -MF $@ $<
|
||||
|
||||
# objects depent on .cpp AND dependency files, which have an empty recipe
|
||||
$(OBJ_DIR)/%.o: %.cpp $(DEP_DIR)/%.d
|
||||
$(OBJ_DIR)%.o: %.cpp $(DEP_DIR)%.d
|
||||
@mkdir -p $(@D)
|
||||
$(DOCKER) $(CXX) -c $(CFLAGS) $(INC) $(DEF) -o $@ $<
|
||||
$(CXX) -c $(CFLAGS) $(INC) $(DEF) -o $@ $<
|
||||
|
||||
# empty recipe for dependency files. This prevents make errors
|
||||
$(DEP):
|
||||
@@ -158,8 +100,8 @@ include $(wildcard $(DEP))
|
||||
$(BUILD_DIR)/$(TARGET): $(OBJ)
|
||||
@mkdir -p $(@D)
|
||||
@echo Linking to target: $(TARGET)
|
||||
@echo $(DOCKER) $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) '$$(OBJ)'
|
||||
@$(DOCKER) $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) $(OBJ)
|
||||
@echo $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) '$$(OBJ)'
|
||||
@$(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) $(OBJ)
|
||||
@echo
|
||||
@echo Print size information
|
||||
@$(CSIZE) $(@D)/$(TARGET)
|
||||
@@ -174,19 +116,43 @@ clean:
|
||||
|
||||
|
||||
#
|
||||
# ================ Local build rules =================
|
||||
# examples:
|
||||
# make MK_ARG="-std=c++14 -fconcepts" build-gcc
|
||||
# make MK_ARG="-std=c++17" build-clang
|
||||
# ============ User Rules =============
|
||||
#
|
||||
.PHONY: build-gcc
|
||||
build-gcc: CFLAGS += $(MK_ARG)
|
||||
build-gcc: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: build-clang
|
||||
build-clang: CXX := $(CLANGXX)
|
||||
build-clang: CFLAGS += $(MK_ARG)
|
||||
build-clang: $(BUILD_DIR)/$(TARGET)
|
||||
.PHONY: gcc14
|
||||
gcc14: CFLAGS += -std=c++14
|
||||
gcc14: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: gcc14_conc
|
||||
gcc14_conc: CFLAGS += -std=c++14 -fconcepts
|
||||
gcc14_conc: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: gcc17
|
||||
gcc17: CFLAGS += -std=c++17
|
||||
gcc17: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: gcc17_conc
|
||||
gcc17_conc: CFLAGS += -std=c++17 -fconcepts
|
||||
gcc17_conc: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: gcc2a
|
||||
gcc2a: CFLAGS += -std=c++2a
|
||||
gcc2a: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: clang14
|
||||
clang14: CXX := $(CLANGXX)
|
||||
clang14: CFLAGS += -std=c++14
|
||||
clang14: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: clang17
|
||||
clang17: CXX := $(CLANGXX)
|
||||
clang17: CFLAGS += -std=c++17
|
||||
clang17: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: clang2a
|
||||
clang2a: CXX := $(CLANGXX)
|
||||
clang2a: CFLAGS += -std=c++2a
|
||||
clang2a: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: debug
|
||||
debug: $(BUILD_DIR)/$(TARGET)
|
||||
@@ -197,22 +163,3 @@ release: clean $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: all
|
||||
all: clean release
|
||||
|
||||
#
|
||||
# ================ Docker based rules ================
|
||||
# examples:
|
||||
# make IMAGE="gcc:8.3" MK_ARG="-std=c++14 -fconcepts" dock-gcc
|
||||
# make IMAGE="a-clang-image" MK_ARG="-std=c++17" dock-clang
|
||||
#
|
||||
.PHONY: dock-gcc
|
||||
dock-gcc: DOCKER := $(DOCKER_RUN) $(IMAGE)
|
||||
dock-gcc: CFLAGS += $(MK_ARG)
|
||||
dock-gcc: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
.PHONY: dock-clang
|
||||
dock-clang: CXX := $(CLANGXX)
|
||||
dock-clang: DOCKER := $(DOCKER_RUN) $(IMAGE)
|
||||
dock-clang: CFLAGS += $(MK_ARG)
|
||||
dock-clang: $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
|
||||
|
||||
+2
-5
@@ -19,14 +19,11 @@
|
||||
*
|
||||
*/
|
||||
#include <gtest/gtest.h>
|
||||
#include <exception>
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) try {
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::cout << "Exception: " << e.what() << '\n';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -140,9 +140,9 @@ namespace TmetaBasic {
|
||||
EXPECT_EQ (true, (std::is_same<true_, and_<true_, true_, true_>>()));
|
||||
EXPECT_EQ (true, (std::is_same<false_, and_<true_, true_, false_>>()));
|
||||
|
||||
EXPECT_EQ (true, (same<Foo, Foo>()));
|
||||
EXPECT_EQ (false, (same<Foo, Bar>()));
|
||||
EXPECT_EQ (true, (not_same<Foo, Bar>()));
|
||||
EXPECT_EQ (true, (same_<Foo, Foo>()));
|
||||
EXPECT_EQ (false, (same_<Foo, Bar>()));
|
||||
EXPECT_EQ (true, (not_same_<Foo, Bar>()));
|
||||
|
||||
}
|
||||
|
||||
@@ -218,11 +218,11 @@ namespace TmetaBasic {
|
||||
/*
|
||||
* SFINAE
|
||||
*/
|
||||
template <typename T, typename =when<same<T, int>::type::value>>
|
||||
template <typename T, typename =when<same_<T, int>::type::value>>
|
||||
int check1 (T x) { return x; }
|
||||
int check1 (...) { return 0; }
|
||||
|
||||
template <typename T, typename =enable_if_t<same<T, int>::type::value, void>>
|
||||
template <typename T, typename =enable_if_t<same_<T, int>::type::value, void>>
|
||||
int check2 (T x) { return x; }
|
||||
int check2 (...) { return 0; }
|
||||
|
||||
|
||||
@@ -174,9 +174,7 @@ namespace TmetaTypelist {
|
||||
EXPECT_EQ (true, (std::is_same<long, at<l, int_<3>>>()));
|
||||
|
||||
EXPECT_EQ (true, (std::is_same<char*, front<l>>()));
|
||||
EXPECT_EQ (true, (std::is_same<nil_, front<typelist<>>>()));
|
||||
EXPECT_EQ (true, (std::is_same<short, back<l>>()));
|
||||
EXPECT_EQ (true, (std::is_same<nil_, back<typelist<>>>()));
|
||||
}
|
||||
|
||||
TEST(TmetaTypelist, Concat) {
|
||||
|
||||
Reference in New Issue
Block a user