Browse Source

DEV: new documentation setup

concepts
parent
commit
d1242f969c
19 changed files with 986 additions and 1047 deletions
  1. +52
    -65
      Doxyfile
  2. +1
    -1
      include/utl/concepts/concepts.h
  3. +0
    -16
      include/utl/concepts/stl.h
  4. +7
    -21
      include/utl/core/crtp.h
  5. +5
    -17
      include/utl/core/impl.h
  6. +6
    -19
      include/utl/core/types.h
  7. +40
    -34
      include/utl/core/version.h
  8. +1
    -0
      include/utl/dev/dev_iterators.h
  9. +415
    -0
      include/utl/meta/basic.h
  10. +34
    -50
      include/utl/meta/detection.h
  11. +0
    -151
      include/utl/meta/integral.h
  12. +149
    -82
      include/utl/meta/invoke.h
  13. +33
    -19
      include/utl/meta/meta.h
  14. +0
    -227
      include/utl/meta/operations.h
  15. +0
    -86
      include/utl/meta/selection.h
  16. +38
    -27
      include/utl/meta/sfinae.h
  17. +127
    -133
      include/utl/meta/typelist.h
  18. +0
    -62
      include/utl/meta/useif.h
  19. +78
    -37
      include/utl/utility/invoke.h

+ 52
- 65
Doxyfile View File

@@ -1,4 +1,4 @@
# Doxyfile 1.8.14
# Doxyfile 1.8.13

# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -20,8 +20,8 @@
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
# built into libc) for the transcoding. See
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
# for the list of possible encodings.
# The default value is: UTF-8.

DOXYFILE_ENCODING = UTF-8
@@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.

OUTPUT_DIRECTORY = W:\Work\Software\Libraries\utl\doc
OUTPUT_DIRECTORY = doc

# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@@ -150,7 +150,7 @@ INLINE_INHERITED_MEMB = NO
# shortest path that makes the file name unique will be used
# The default value is: YES.

FULL_PATH_NAMES = YES
FULL_PATH_NAMES = NO

# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
@@ -337,7 +337,7 @@ BUILTIN_STL_SUPPORT = YES
CPP_CLI_SUPPORT = NO

# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
@@ -360,14 +360,14 @@ IDL_PROPERTY_SUPPORT = YES
# all members of a group must be documented explicitly.
# The default value is: NO.

DISTRIBUTE_GROUP_DOC = NO
DISTRIBUTE_GROUP_DOC = YES

# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.

GROUP_NESTED_COMPOUNDS = NO
GROUP_NESTED_COMPOUNDS = YES

# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
@@ -408,7 +408,7 @@ INLINE_SIMPLE_STRUCTS = NO
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.

TYPEDEF_HIDES_STRUCT = NO
TYPEDEF_HIDES_STRUCT = YES

# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
@@ -435,7 +435,7 @@ LOOKUP_CACHE_SIZE = 0
# normally produced when WARNINGS is set to YES.
# The default value is: NO.

EXTRACT_ALL = YES
EXTRACT_ALL = NO

# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
@@ -447,7 +447,7 @@ EXTRACT_PRIVATE = YES
# scope will be included in the documentation.
# The default value is: NO.

EXTRACT_PACKAGE = YES
EXTRACT_PACKAGE = NO

# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
@@ -469,7 +469,7 @@ EXTRACT_LOCAL_CLASSES = YES
# included.
# The default value is: NO.

EXTRACT_LOCAL_METHODS = YES
EXTRACT_LOCAL_METHODS = NO

# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
@@ -486,7 +486,7 @@ EXTRACT_ANON_NSPACES = NO
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.

HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_MEMBERS = YES

# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
@@ -494,7 +494,7 @@ HIDE_UNDOC_MEMBERS = NO
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.

HIDE_UNDOC_CLASSES = NO
HIDE_UNDOC_CLASSES = YES

# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
@@ -508,14 +508,14 @@ HIDE_FRIEND_COMPOUNDS = NO
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.

HIDE_IN_BODY_DOCS = NO
HIDE_IN_BODY_DOCS = YES

# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.

INTERNAL_DOCS = NO
INTERNAL_DOCS = YES

# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
@@ -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 = YES
SORT_MEMBER_DOCS = NO

# 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
@@ -708,7 +708,7 @@ LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
@@ -790,12 +790,12 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.

INPUT =
INPUT = .

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
# possible encodings.
# The default value is: UTF-8.

@@ -873,7 +873,11 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.

EXCLUDE = test
EXCLUDE = test \
include/utl/dev \
include/utl/concepts \
include/utl/com \
include/utl/container

# 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
@@ -1043,7 +1047,7 @@ SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
# (see https://www.gnu.org/software/global/global.html). You will need version
# (see http://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
@@ -1079,7 +1083,7 @@ VERBATIM_HEADERS = YES
# generated with the -Duse-libclang=ON option for CMake.
# The default value is: NO.

CLANG_ASSISTED_PARSING = NO
CLANG_ASSISTED_PARSING = YES

# If clang assisted parsing is enabled you can provide the compiler with command
# line options that you would normally use when invoking the compiler. Note that
@@ -1087,18 +1091,7 @@ CLANG_ASSISTED_PARSING = NO
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.

CLANG_OPTIONS =

# If clang assisted parsing is enabled you can provide the clang parser with the
# path to the compilation database (see:
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
# were built. This is equivalent to specifying the "-p" option to a clang tool,
# such as clang-check. These options will then be pased to the parser.
# Note: The availability of this option depends on whether or not doxygen was
# generated with the -Duse-libclang=ON option for CMake.
# The default value is: 0.

CLANG_COMPILATION_DATABASE_PATH= 0
CLANG_OPTIONS = -std=c++14

#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
@@ -1218,7 +1211,7 @@ HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
@@ -1254,17 +1247,6 @@ HTML_COLORSTYLE_GAMMA = 80

HTML_TIMESTAMP = NO

# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
# are dynamically created via Javascript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML
# page. Disable this option to support browsers that do not have Javascript,
# like the Qt help browser.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.

HTML_DYNAMIC_MENUS = YES

# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
@@ -1288,12 +1270,12 @@ HTML_INDEX_NUM_ENTRIES = 100

# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/tools/xcode/), introduced with
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1409,7 +1391,7 @@ QCH_FILE =

# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace).
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.

@@ -1417,7 +1399,8 @@ QHP_NAMESPACE = org.doxygen.Project

# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders).
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
# folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.

@@ -1425,21 +1408,23 @@ QHP_VIRTUAL_FOLDER = doc

# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.

QHP_CUST_FILTER_NAME =

# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.

QHP_CUST_FILTER_ATTRS =

# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes).
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.

QHP_SECT_FILTER_ATTRS =
@@ -1532,7 +1517,7 @@ EXT_LINKS_IN_WINDOW = NO

FORMULA_FONTSIZE = 10

# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
@@ -1544,7 +1529,7 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES

# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# https://www.mathjax.org) which uses client side Javascript for the rendering
# http://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
@@ -1571,7 +1556,7 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# MathJax from http://www.mathjax.org before deployment.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.

@@ -1633,7 +1618,7 @@ SERVER_BASED_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/).
# Xapian (see: http://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@@ -1646,7 +1631,7 @@ EXTERNAL_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). See the section "External Indexing and
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.

@@ -1833,7 +1818,7 @@ LATEX_SOURCE_CODE = NO

# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.

@@ -2016,9 +2001,9 @@ DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------

# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
# the structure of the code including all documentation. Note that this feature
# is still experimental and incomplete at the moment.
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
# structure of the code including all documentation. Note that this feature is
# still experimental and incomplete at the moment.
# The default value is: NO.

GENERATE_AUTOGEN_DEF = NO
@@ -2231,7 +2216,7 @@ HIDE_UNDOC_RELATIONS = YES
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
# The default value is: YES.

HAVE_DOT = NO

@@ -2387,7 +2372,9 @@ DIRECTORY_GRAPH = YES
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.


+ 1
- 1
include/utl/concepts/concepts.h View File

@@ -19,7 +19,7 @@
*
*/
#ifndef __utl_concepts_concepts_h__
#define __utl_consepts_concepts_h__
#define __utl_concepts_concepts_h__
#include <utl/core/impl.h>


+ 0
- 16
include/utl/concepts/stl.h View File

@@ -1,22 +1,6 @@
/*!
* \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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __utl_concepts_stl_h__
#define __utl_concepts_stl_h__


+ 7
- 21
include/utl/core/crtp.h View File

@@ -1,22 +1,6 @@
/*!
* \file /utl/impl/crtp.h
* \file utl/core/crtp.h
* \brief CRTP idiom 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __utl_impl_crtp_h__
#define __utl_impl_crtp_h__
@@ -25,12 +9,14 @@
/*!
* \defgroup crtp CRTP idiom support header
* \ingroup impl
* \ingroup core
*
* 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 \ref virtual_tag can passed to base class. The rest
* CRTP type, the \c virtual_tag can passed to base class. The rest
* will handled by utl automatically.
*
* \sa utl::virtual_tag
*/
//!@{
namespace utl {
@@ -41,8 +27,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); }
}
//!@}


+ 5
- 17
include/utl/core/impl.h View File

@@ -1,30 +1,18 @@
/*!
* \file /utl/core/impl.h
* \file utl/core/impl.h
* \brief Implementation detail main forward 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __utl_core_impl_h__
#define __utl_core_impl_h__
//! \defgroup core Core
//! Provide compiler feature support macros, uTL version,
//! global types etc...
// FWD include implementation details once
#include <utl/core/version.h>
#include <utl/core/types.h>
#include <utl/core/crtp.h>
#endif /* __utl_core_impl_h__ */

+ 6
- 19
include/utl/core/types.h View File

@@ -1,23 +1,8 @@
/*!
* \file /utl/core/types.h
* \file utl/core/types.h
* \brief Basic type alias support
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __utl_core_types_h__
#define __utl_core_types_h__
@@ -27,13 +12,15 @@
//#include <type_traits>
namespace utl {
//! @{ \name byte and word types
//! \name byte and word types
//! @{
using byte_t = uint8_t; //!< 8 bits wide
using word_t = uint16_t; //!< 16 bits wide
using dword_t = uint32_t; //!< 32 bits wide
//! @}
//! @{ \name size and index
//! \name size and index
//! @{
using size_t = std::size_t;
using index_t = size_t; //!< index_t and size_t mend to be interchangeable


+ 40
- 34
include/utl/core/version.h View File

@@ -1,46 +1,44 @@
/*!
* \file /utl/core/version.h
* \brief version and cpp version checks
*
* 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 <http://www.gnu.org/licenses/>.
*
* \file utl/core/version.h
* \brief utl version and cpp version checks
*/
#ifndef __utl_core_version_h__
#define __utl_core_version_h__
//!\defgroup version version
//! Definitions of the utl version
//!\addtogroup core
//! @{
//! \defgroup version Version
//! Definitions of the utl version and compiler features
//!@{
//! utl version
//! utl version as string
#define UTL_VERSION "0.1.0"
#define UTL_VERSION_MAJOR 0
#define UTL_VERSION_MINOR 1
#define UTL_VERSION_PATCH 0
//! utl version as integer
//!
//! 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$
#define UTL_VERSION_VALUE ( (UTL_VERSION_MAJOR * 10000) \
+ (UTL_VERSION_MINOR * 100) \
+ UTL_VERSION_PATCH)
//! C++ versions
#define CXX_VER __cplusplus
#define CXX_VER_STD_11 201103L
#define CXX_VER_STD_14 201402L
#define CXX_VER_STD_17 201703L
//!@}
//! \name Compiler and feature checks
//! These checks are used inside uTL, but the user is free to use the as well.
//! @{
#define CXX_VER __cplusplus //!< Current compiler's version
#define CXX_VER_STD_11 201103L //!< C++11
#define CXX_VER_STD_14 201402L //!< C++14
#define CXX_VER_STD_17 201703L //!< C++17
//! Check for variable templates
//! \def CXX_VARIABLE_TEMPLATES
//! Check for variable templates (Non-zero if available)
#ifndef CXX_VARIABLE_TEMPLATES
#ifdef __cpp_variable_templates
#define CXX_VARIABLE_TEMPLATES __cpp_variable_templates
@@ -49,7 +47,8 @@
#endif
#endif
//! Check concepts
//! \def CXX_CONCEPTS
//! Check for concepts (Non-zero if available)
#ifndef CXX_CONCEPTS
#ifdef __cpp_concepts
#define CXX_CONCEPTS __cpp_concepts
@@ -58,7 +57,8 @@
#endif
#endif
//! Check for inline variables
//! \def CXX_INLINE_VARIABLES
//! Check for inline variables (Non-zero if available)
#ifndef CXX_INLINE_VARIABLES
#ifdef __cpp_inline_variables
#define CXX_INLINE_VARIABLES __cpp_inline_variables
@@ -67,6 +67,8 @@
#endif
#endif
//! \def CXX_FOLD_EXPRESSIONS
//! Check for fold expressions (Non-zero if available)
#ifndef CXX_FOLD_EXPRESSIONS
#ifdef __cpp_fold_expressions
#define CXX_FOLD_EXPRESSIONS __cpp_fold_expressions
@@ -75,19 +77,23 @@
#endif
#endif
/*
* Workaround inspections
*/
//! @}
//! \name Workaround inspections
//! @{
#if defined(__GNUC__) && (__GNUC__ < 5)
// https://wg21.link/cwg1558
#define UTL_WORKAROUND_CWG_1558
#endif
//! Base library requirement
#if CXX_VER < CXX_VER_STD_14
#error "uTL requires C++14"
#endif
//!@}
//! @}
//! @}
#endif /* #ifndef __utl_core_version_h__ */

+ 1
- 0
include/utl/dev/dev_iterators.h View File

@@ -23,6 +23,7 @@
#include <utl/core/impl.h>
#include <utl/meta/meta.h>
#include <iterator>
namespace utl {


+ 415
- 0
include/utl/meta/basic.h View File

@@ -0,0 +1,415 @@
/*!
* \file utl/meta/basic.h
* \brief Template meta-programming basic definitions
*/
#ifndef __utl_meta_basic_h__
#define __utl_meta_basic_h__
#include <utl/core/impl.h>
#include <type_traits>
#include <utility>
/*!
* \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 <typename Tp>
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 <typename Tp>
using eval_v = typename eval<Tp>::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 <typename Tp, Tp v>
using integral_ = std::integral_constant<Tp, v>;
//! \name Wrappers for basic types
//! @{
//! bool_ type: integral constant wrapper for bool
template<bool v>
using bool_ = integral_<bool, v>;
using true_ = bool_<true>; //!< The type used as a compile-time boolean with true value.
using false_ = bool_<false>; //!< The type used as a compile-time boolean with false value.
//! int8_ type: integral constant wrapper for \c int8_t
template<int8_t v>
using int8_ = integral_<int8_t, v>;
//! uint8_ type: integral constant wrapper for \c uint8_t
template<uint8_t v>
using uint8_ = integral_<uint8_t, v>;
//! int16_ type: integral constant wrapper for \c int16_t
template<int16_t v>
using int16_ = integral_<int16_t, v>;
//! uint16_ type: integral constant wrapper for \c uint16_t
template<uint16_t v>
using uint16_ = integral_<uint16_t, v>;
//! int32_ type: integral constant wrapper for \c int32_t
template<int32_t v>
using int32_ = integral_<int32_t, v>;
//! uint32_ type: integral constant wrapper for \c uint32_t
template<uint32_t v>
using uint32_ = integral_<uint32_t, v>;
//! char_ type: integral constant wrapper for \c char
template<char v>
using char_ = integral_<char, v>;
//! int_ type: integral constant wrapper for \c int
template<int v>
using int_ = integral_<int, v>;
//! long_ type: integral constant wrapper for \c long
template<long v>
using long_ = integral_<long, v>;
//! index_ type: integral constant wrapper for \c index_t a.k.a std::size_t
template<index_t v>
using index_ = integral_<index_t, v>;
//! size_ type: integral constant wrapper for \c size_t a.k.a std::size_t
template<size_t v>
using size_ = integral_<size_t, v>;
//! The last position we can express for indexing
using Npos = size_<index_t(-1)>;
//! @}
//! \name unevaluated expressions
//! @{
//! Computes the size of the type \p Tp.
//! Complexity \f$ O(1) \f$.
template <typename Tp>
using sizeof_ = size_<sizeof(Tp)>;
//! Computes the alignment required for any instance of the type \p Tp.
//! Complexity \f$ O(1) \f$.
template <typename Tp>
using alignof_ = size_<alignof(Tp)>;
//! @}
//! \name integer sequence
//! @{
template< class Tp, Tp... Ints >
using integer_sequence = std::integer_sequence<Tp, Ints...>;
template<typename Tp, Tp Num>
using make_integer_sequence = std::make_integer_sequence<Tp, Num>;
//! Alias template index_sequence
template<index_t... Idx>
using index_sequence = integer_sequence<index_t, Idx...>;
//! Alias template make_index_sequence
template<index_t Num>
using make_index_sequence = make_integer_sequence <index_t, Num>;
//! Alias template index_sequence_for
template<typename... Types>
using index_sequence_for = make_index_sequence<sizeof...(Types)>;
//! @}
}}
//!@}
/*!
* \ingroup basic
* \defgroup selection Selection
* Type selection support header
*/
//! @{
namespace utl {
namespace meta{
//! \name if implementation
//! @{
namespace details {
template <bool If, typename...>
struct if_c_ {
using type = nil_; //< avoid ill formed result
};
template<typename Then>
struct if_c_<true, Then> {
using type = Then;
};
template<typename Then, typename Else>
struct if_c_<true, Then, Else> {
using type = Then;
};
template<typename Then, typename Else>
struct if_c_<false, Then, Else> {
using type = Else;
};
}
//! Select one type or another depending on a compile-time Boolean.
template <bool B, typename... Args>
using if_c = eval<details::if_c_<B, Args...>>;
//! Select one type or another depending on a compile-time Boolean type
template <typename If, typename... Args>
using if_ = if_c<If::type::value, Args...>;
//! @}
/*!
* \name Named type selectors
*/
//! @{
//! Select the first type of a type sequence
template <typename T1, typename ...> using first_of = T1;
//! Select the second type of a type sequence
template <typename T1, typename T2, typename ...> 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 <bool B>
using not_c = bool_<!B>;
//! negate the bool_ parameter and return bool_
template<typename Tp>
using not_ = not_c<Tp::type::value>;
//! \name OR implementation
//! @{
namespace details {
template<typename...> struct _or_;
template<>
struct _or_<> : false_ { };
template<typename T1>
struct _or_<T1> : T1 { };
template<typename T1, typename T2>
struct _or_ <T1, T2>
: if_<T1, T1, T2> { };
template<typename T1, typename T2, typename T3, typename... Tn>
struct _or_<T1, T2, T3, Tn...>
: if_<T1, T1, _or_<T2, T3, Tn...>> { };
}
//! Operator or for bool_ types
//! \tparam Ts Variadic args of type bool_
//! \return Logical or as bool_
template <typename... Ts>
using or_ = eval<details::_or_<Ts...>>;
//! @}
//! \name AND implementation
//! @{
namespace details {
template<typename...> struct _and_;
template<>
struct _and_<>
: true_ { };
template<typename T1>
struct _and_ <T1>
: T1 { };
template<typename T1, typename T2>
struct _and_<T1, T2>
: if_<T1, T2, T1> { };
template<typename T1, typename T2, typename T3, typename... Tn>
struct _and_<T1, T2, T3, Tn...>
: if_<T1, _and_<T2, T3, Tn...>, T1> { };
}
//! Operator and for bool_ types
//! \tparam Ts Variadic args of type bool_
//! \return Logical and as bool_
template <typename... Ts>
using and_ = eval<details::_and_<Ts...>>;
//! @}
//! \name same
//! @{
template<typename T1, typename T2>
struct same_ : false_ { };
template<typename Tp>
struct same_ <Tp, Tp> : true_ { };
template<typename T1, typename T2>
using not_same_ = not_<eval<same_<T1, T2>>>;
//! @}
//! @}
}}
//! @}
/*!
* \ingroup basic
* \defgroup integral_operators integral operators
* Type arithmetic and operations
*/
//! @{
namespace utl {
namespace meta {
/*!
* \name Math operations
*/
//! @{
//! Negation
template <typename Tp>
using negate = integral_<decltype(-Tp()), -Tp()>;
//! Addition
template <typename Tp1, typename Tp2>
using add = integral_<
decltype(Tp1() + Tp2()),
Tp1() + Tp2()
>;
//! Multiplication
template <typename Tp1, typename Tp2>
using mult = integral_<
decltype(Tp2() * Tp2()),
Tp1() * Tp2()
>;
//! Division
template <typename Tp1, typename Tp2>
using divide = integral_<
decltype(Tp2() / Tp2()),
Tp1() / Tp2()
>;
//! Modulo
template <typename Tp1, typename Tp2>
using modulo = integral_<
decltype(Tp1() % Tp2()),
Tp1() % Tp2()
>;
//! Substruction
template <typename Tp1, typename Tp2>
using sub = add<Tp1, negate<Tp2>>;
//! Increase
template <typename Tp>
using inc = add<Tp, int_<1>>;
//! decrease
template <typename Tp>
using dec = add<Tp, int_<-1>>;
//! @}
/*!
* \name Comparison operations
*/
//! @{
//! \return a true-valued Integral Constant if Tp1 and Tp2 are equal.
template <typename Tp1, typename Tp2> using comp_eq = bool_<Tp1() == Tp2()>;
//! \return a true-valued Integral Constant if Tp1 is less than Tp2.
template <typename Tp1, typename Tp2> using comp_lt = bool_<(Tp1() < Tp2())>;
//! Not equal
template <typename Tp1, typename Tp2> using comp_ne = not_<comp_eq<Tp1, Tp2>>;
//! Greater than
template <typename Tp1, typename Tp2> using comp_gt = comp_lt <Tp2, Tp1>;
//! Less or equal
template <typename Tp1, typename Tp2> using comp_le = not_<comp_lt<Tp2, Tp1>>;
//! Greater or equal
template <typename Tp1, typename Tp2> using comp_ge = not_<comp_lt<Tp1, Tp2>>;
//! @}
/*!
* \name Bitwise operations
*/
//! @{
//! \return bitwise not (~) operation of its argument.
template <typename T> using bitnot_ = integral_<typename T::value_type, (typename T::value_type)(~T())>;
//! \return bitwise and (&) operation of its arguments
template <typename Tp1, typename Tp2>
using bitand_ = integral_<decltype(Tp1() & Tp2()), Tp1() & Tp2()>;
//! \return bitwise or (|) operation of its arguments.
template <typename Tp1, typename Tp2>
using bitor_ = integral_<decltype(Tp1() | Tp2()), Tp1() | Tp2()>;
//! \return bitwise xor (^) operation of its arguments.
template <typename Tp1, typename Tp2>
using bitxor_ = integral_<decltype(Tp1() ^ Tp2()), Tp1() ^ Tp2()>;
//! \return the result of bitwise shift left (<<) operation on Tp.
template <typename Tp, typename shift>
using shift_left = integral_<typename Tp::value_type, (typename Tp::value_type)(Tp() << shift())>;
//! \return the result of bitwise shift right (>>) operation on Tp.
template <typename Tp, typename shift>
using shift_right = integral_<typename Tp::value_type, (typename Tp::value_type)(Tp() >> shift())>;
//! @}
}}
//! @}
//! @}
#endif /* __utl_meta_basic_h__ */

+ 34
- 50
include/utl/meta/detection.h View File

@@ -1,34 +1,17 @@
/*!
* \file detection.h
* \brief Detection idiom based on WG21's N4502 [\ref 1] from Walter E. Brown
*
* 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 <http://www.gnu.org/licenses/>.
*
* \anchor [1]: www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf
* \brief Detection idiom based on WG21's N4502 from Walter E. Brown
*/
#ifndef __utl_meta_detection_h__
#define __utl_meta_detection_h__
#include <utl/core/impl.h>
#include <utl/meta/operations.h>
#include <utl/meta/basic.h>
#include <type_traits>
/*!
* \ingroup meta
* \defgroup detection
* \defgroup detection Detection
* Detection idiom support header.
*/
//! @{
@@ -37,7 +20,7 @@ namespace utl {
namespace meta {
/*!
* void_t meta-function that maps a sequence of any types to the type void
* \name void_t implementation
*/
//! @{
#if defined(UTL_WORKAROUND_CWG_1558)
@@ -49,16 +32,18 @@ namespace meta {
template<typename... _Ts>
using void_t = eval<void_<_Ts...>>;
#else
//! void_ type alias
//! void_ meta-function that maps a sequence of any types to the type void
template <typename...> using void_ = void;
//! void_t type alias
//! void_t meta-function that maps a sequence of any types to the type void
template <typename...> using void_t = void;
#endif
//! @}
/*!
* Not a type to use in detected idiom. This type can
* not be constructed, destructed or copied
* \brief
* Not a type to use in detected idiom.
*
* This type can not be constructed, destructed or copied.
*/
struct nat_ {
nat_() = delete;
@@ -67,9 +52,9 @@ namespace meta {
void operator = (nat_ const&) = delete;
};
//! Detector for detection idiom
//! \name Detector for detection idiom
//! @{
namespace detail {
namespace details {
template <typename Default,
typename AlwaysVoid,
template<typename...> class Op, typename... Args>
@@ -89,24 +74,23 @@ namespace meta {
template <typename Default,
template<typename...> class Op, typename... Args>
using detected_or = detector<Default, void, Op, Args...>;
} // namespace detail
} // namespace details
//! @}
/*!
* detection interface
* \name detection interface
*/
//! @{
/*!
* Checks if Op<Args...> is a valid expression without evaluating it.
*
* \tparam Op a meta-callback function to pass Args...
* \tparam Args... types to pass to Op for checking
* \tparam Op a meta-callback function to pass Args...
* \tparam Args... types to pass to Op for checking
* \return status of the operation [bool_]
* \arg true_ if Op<Args...> is valid expression
* \arg false_ if Op<Args...> is not valid
*
* \example
* \code
* // archetypal alias for a copy assignment operation
* template< class T > using copy_assign_t = decltype( declval<T&>() = declval<T const &>() );
@@ -115,7 +99,7 @@ namespace meta {
* \endcode
*/
template <template<typename...> class Op, typename... Args>
using is_detected = typename detail::detector<nat_, void, Op, Args...>::detected;
using is_detected = typename details::detector<nat_, void, Op, Args...>::detected;
//! Detection predicate
template< template<typename...> class Op, typename... Args>
@@ -124,12 +108,12 @@ namespace meta {
/*!
* Detection tool that evaluates to Op<Args...> if it's valid and to nat_ if not
*
* \param Op metafunction detector
* \param Args... The arguments to pass to \p Op and check if is well formed
* \tparam Op metafunction detector
* \tparam Args... The arguments to pass to \p Op and check if is well formed
* \return The result type
* \arg Op<Args...> if is well formed
* \arg nat_ if Op<Args...> is ill formed
* \example
*
* \code
* template <typename T> using try_type = typename T::type; // detector
* template <typename T> using try_ppT = decltype (++(std::declval<T>())); // detector
@@ -142,19 +126,19 @@ namespace meta {
*/
template <template<typename...> class Op, typename... Args>
using detected_t = eval <
detail::detector<nat_, void, Op, Args...>
details::detector<nat_, void, Op, Args...>
>;
/*!
* Detection tool that evaluates to Op<Args...> if it's valid and to \p Default if not
*
* \param Default The resulting type if detection fail
* \param Op metafunction detector
* \param Args... The arguments to pass to \p Op and check if is well formed
* \tparam Default The resulting type if detection fail
* \tparam Op metafunction detector
* \tparam Args... The arguments to pass to \p Op and check if is well formed
* \return The result type
* \arg Op<Args...> if is well formed
* \arg Default if Op<Args...> is ill formed
* \example
*
* \code
* template <typename T> using try_type = typename T::type; // detector
* template <typename T> using try_ppT = decltype (++(std::declval<T>())); // detector
@@ -168,20 +152,20 @@ namespace meta {
template <typename Default,
template<typename...> class Op, typename... Args>
using detected_or_t = eval <
detail::detected_or<Default, Op, Args...>
details::detected_or<Default, Op, Args...>
>;
/*!
* Detection tool that evaluates to true_ if evaluation of Op<Args...>
* is \p Expected and to false_ if not
*
* \param Expected The expected resulting type if detection succeed
* \param Op metafunction detector
* \param Args... The arguments to pass to \p Op and check if is well formed
* \tparam Expected The expected resulting type if detection succeed
* \tparam Op metafunction detector
* \tparam Args... The arguments to pass to \p Op and check if is well formed
* \return The result type
* \arg true_ if Op<Args...> is well formed and evaluate to Expected
* \arg false_ Any other case
* \example
*
* \code
* template <typename T> using try_type = typename T::type; // detector
* template <typename T> using try_ppT = decltype (++(std::declval<T>())); // detector
@@ -207,13 +191,13 @@ namespace meta {
* Detection tool that evaluates to true_ if evaluation of Op<Args...> is convertible
* to \p To and to false_ if not
*
* \param To The to convert to if detection succeed
* \param Op metafunction detector
* \param Args... The arguments to pass to \p Op and check if is well formed
* \tparam To The to convert to if detection succeed
* \tparam Op metafunction detector
* \tparam Args... The arguments to pass to \p Op and check if is well formed
* \return The result type
* \arg true_ if Op<Args...> is well formed and convertible to To
* \arg false_ Any other case
* \example
*
* \code
* template <typename T> using try_type = typename T::type; // detector
* template <typename T> using try_ppT = decltype (++(std::declval<T>())); // detector


+ 0
- 151
include/utl/meta/integral.h View File

@@ -1,151 +0,0 @@
/*!
* \file integralconstant.h
* \brief Template meta-programming integral constant
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_integralconstant_h__
#define __utl_meta_integralconstant_h__
#include <utl/core/impl.h>
#include <type_traits>
#include <utility>
/*!
* \ingroup meta
* \defgroup integral
* integral constant support header
*/
//! @{
namespace utl {
namespace meta {
/*!
* Empty type
* utl::meta's nil type is not pure nil. It's a recursive "de-referencable nil.
* Each time someone applies ::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 \p Tp::type. Used to evaluate/extract return type of metafunctions
template <typename Tp>
using eval = typename Tp::type;
//! integral_
//! Integral Constant is a holder class for a compile-time value of an integral type.
//! Every Integral Constant is also a null-ary Metafunction, returning itself.
//! An integral constant object is implicitly convertible to the corresponding
//! run-time value of the wrapped integral type
//! @{
template <typename Tp, Tp v>
using integral_ = std::integral_constant<Tp, v>;
//! @}
//! Wrappers for basic types
//! @{
//! bool_ type: integral constant wrapper for bool
template<bool v>
using bool_ = integral_<bool, v>;
using true_ = bool_<true>; //!< The type used as a compile-time boolean with true value.
using false_ = bool_<false>; //!< The type used as a compile-time boolean with false value.
//! int8_ type: integral constant wrapper for \c int8_t
template<int8_t v>
using int8_ = integral_<int8_t, v>;
//! uint8_ type: integral constant wrapper for \c uint8_t
template<uint8_t v>
using uint8_ = integral_<uint8_t, v>;
//! int16_ type: integral constant wrapper for \c int16_t
template<int16_t v>
using int16_ = integral_<int16_t, v>;
//! uint16_ type: integral constant wrapper for \c uint16_t
template<uint16_t v>
using uint16_ = integral_<uint16_t, v>;
//! int32_ type: integral constant wrapper for \c int32_t
template<int32_t v>
using int32_ = integral_<int32_t, v>;
//! uint32_ type: integral constant wrapper for \c uint32_t
template<uint32_t v>
using uint32_ = integral_<uint32_t, v>;
//! char_ type: integral constant wrapper for \c char
template<char v>
using char_ = integral_<char, v>;
//! int_ type: integral constant wrapper for \c int
template<int v>
using int_ = integral_<int, v>;
//! long_ type: integral constant wrapper for \c long
template<long v>
using long_ = integral_<long, v>;
//! index_ type: integral constant wrapper for \c index_t a.k.a std::size_t
template<index_t v>
using index_ = integral_<index_t, v>;
//! size_ type: integral constant wrapper for \c size_t a.k.a std::size_t
template<size_t v>
using size_ = integral_<size_t, v>;
//! Computes the size of the type \p Tp.
//! Complexity \f$ O(1) \f$.
template <typename Tp>
using sizeof_ = size_<sizeof(Tp)>;
//! Computes the alignment required for any instance of the type \p Tp.
//! Complexity \f$ O(1) \f$.
template <typename Tp>
using alignof_ = size_<alignof(Tp)>;
//! @}
//! The last position we can express for indexing
using Npos = size_<index_t(-1)>;
//! integer sequence
//! @{
template< class Tp, Tp... Ints >
using integer_sequence = std::integer_sequence<Tp, Ints...>;
template<typename Tp, Tp Num>
using make_integer_sequence = std::make_integer_sequence<Tp, Num>;
//! Alias template index_sequence
template<index_t... Idx>
using index_sequence = integer_sequence<index_t, Idx...>;
//! Alias template make_index_sequence
template<index_t Num>
using make_index_sequence = make_integer_sequence <index_t, Num>;
//! Alias template index_sequence_for
template<typename... Types>
using index_sequence_for = make_index_sequence<sizeof...(Types)>;
//! @}
}}
//!@}
#endif /* __utl_meta_integralconstant_h__ */

+ 149
- 82
include/utl/meta/invoke.h View File

@@ -1,75 +1,64 @@
/*!
* \file invoke.h
* \file utl/meta/invoke.h
* \brief Template meta-programming utilities for callables
*
* 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 detail.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_invoke_h__
#define __utl_meta_invoke_h__
#include <utl/core/impl.h>
#include <utl/meta/integral.h>
#include <utl/meta/basic.h>
#include <utl/meta/detection.h>
#include <utl/meta/operations.h>
/*!
* \ingroup meta
* \defgroup invoke
* \defgroup meta_invoke Invoke
* A meta-programming invoke() analogous.
*
* This module provides <b>higher order</b> tools to meta. utl::meta's metafunctions inputs are types.
* The metafunctions though are templates in the form of `template <typename...> class`.
* So we can not pass metafunctions to other metafunctions. The utl::meta provides tools to wrap metafunctions
* in a type. This way we create the concepts of:
*
* - <b>\c invocable</b> which is a type containing a metafunction inside.
* - <b>\c evaluation</b> which is the way of unwrapping the metafunction inside the invocable type.
*
* In order to accomplish that, by convention, a \c meta::invocable shall contain a nested
* template type named \c apply which is bind to actual invocable meta-function. Then we can:
*
* - Use \c wrap<> or even better \c quote<> in order to wrap a metafunction to a type (metafunction class)
* - Pass these wrapped types to other metafunctions
* - \c invoke<> the inner \c apply from a wrapped metafunction class.
*/
//! @{
namespace utl {
namespace meta{
/*!
* \name meta::invoke
*
* A meta-programming invoke() analogous. A \c meta::invocable shall contain a nested
* template type named \b apply which is bind to actual invocable meta-function.
*
* - We can use \c wrap<> or even better \c quote<> in order to wrap a metafunction to a type (metafunction class)
* - We can pass these wrapped types to other metafunctions
* - We can \c invoke<> the inner \c apply from a wrapped metafunction class.
* \name identity implementation
*/
//! @{
/*!
* identity, identity_t.
*/
//! @{
template <typename _Tp>
//! Identity is a metafunction always return the input type
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>>;
//! @}
/*!
* invoke, invoke_t
* \name invoke, invoke_t
*/
//! @{
/*!
@@ -88,13 +77,19 @@ namespace meta{
using invoke_t = eval< invoke <Fn, Args...>>;
//! @}
//! wrap
//! \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
* them \c invoke the inner templated apply.
*
* \tparam F The metafunction to wrap
*/
template <template <typename...> class F>
struct wrap {
@@ -102,7 +97,19 @@ namespace meta{
using apply = F<Args...>;
};
//! Wrap a template \p F taking literal constants of type \p T into an Invokable
/*!
* \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
*/
template <typename T, template <T...> class F>
struct wrap_i {
// requires meta::Integral
@@ -111,9 +118,9 @@ namespace meta{
};
//! @}
//! Is applicable trait
//! \name Is applicable trait
//! @{
namespace detail {
namespace details {
template<template<typename...> class F, typename... T>
struct is_applicable_ {
@@ -156,29 +163,51 @@ namespace meta{
};
}
//! check if we can instantiate \p F with parameters \p T
template<template<typename...> class F, typename... T>
/*!
* \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>
using is_applicable_t = eval<
detail::is_applicable_<F, T...>
details::is_applicable_<F, Ts...>
>;
//! check if we can invoke \p Q with parameters \p T
template<typename Q, typename... 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>
using is_applicable_qt = eval <
detail::is_applicable_q_ <Q, T...>
details::is_applicable_q_ <Q, Ts...>
>;
//! check if we can instantiate \p F with parameters \p Is of type \p 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
*/
template <typename T, template<T...> class F, T... Is>
using is_applicable_it = eval<
detail::is_applicable_i_<T, F, Is...>
details::is_applicable_i_<T, F, Is...>
>;
//! @}
//! defer
//! \name defer
//! @{
namespace detail {
//! @{
namespace details {
template<template<typename...> class F, typename... Ts>
struct defer_ {
using type = F<Ts...>;
@@ -194,41 +223,64 @@ namespace meta{
//! template<template<typename...> class F, typename... Ts>
//! using defer_ = F<Ts...>;
//!
//! The use of struct here is due to Core issue 1430 [\ref link1 1] and is used
//! as suggested by Roy Crihfield in [\ref link2 2].
//! The use of struct here is due to Core issue 1430 [1] and is used
//! as suggested by Roy Crihfield in [2].
//! In short, this is due to language's inability to expand Ts... into
//! a fixed parameter list of an alias template.
//!
//! \anchor link1 [1]: https://wg21.link/cwg1430
//! \anchor link2 [2]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498
//! @}
//! [1] https://wg21.link/cwg1430\n
//! [2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498
}
//! defer alias template for F<Ts...>
/*!
* \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
*/
template<template<class...> class F, class... Ts>
using defer = if_<
detail::is_applicable_<F, Ts...>,
detail::defer_<F, Ts...>,
details::is_applicable_<F, Ts...>,
details::defer_<F, Ts...>,
nil_ //!< Safe, nil_ is dereferencable
>;
//! defer_i alias template for F<T, Is...>
/*!
* \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
*/
template <typename T, template<T...> class F, T... Is>
using defer_i = if_ <
detail::is_applicable_i_<T, F, Is...>,
detail::defer_i_<T, F, Is...>,
details::is_applicable_i_<T, F, Is...>,
details::defer_i_<T, F, Is...>,
nil_ //!< Safe, nil_ is dereferencable
>;
//! @}
//! quote
//! \name quote
//! @{
/*!
* quote deferred is a higher-order primitive that wraps an n-ary Metafunction
* \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
* to create a corresponding Metafunction Class (Invocable) using defer<> to
* postpone the evaluation of Metafunction. This is a safe version of \c wrap<>.
* 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 F The metafunction to wrap
*/
template <template <typename...> class F>
struct quote {
@@ -238,7 +290,21 @@ namespace meta{
>;
};
//! Wrap a template \p F taking literal constants of type \p T into an Invokable
/*!
* \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
*/
template <typename T, template <T...> class F>
struct quote_i {
// requires meta::Integral
@@ -249,9 +315,9 @@ namespace meta{
};
//! @}
//! compose
//! \name compose
//! @{
namespace detail {
namespace details {
template <template <typename...> class... Fns> struct compose_f_ {};
// recursive call to all invokes
@@ -292,12 +358,13 @@ namespace meta{
}
/*!
* Create an invocable from other invocables(quoted metafunctions) by composition.
* \brief
* 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
* type. So for n-ary invocables in the N-1 places the typelist<> is the solution.
* \example
*
* \code
* static_assert( std::is_same<
* invoke<compose<quote<F1>, quote<F2>, quote<F3>>, int>, F1<F2<F3<int>>>
@@ -305,15 +372,16 @@ namespace meta{
* \endcode
*/
template <typename... Fns>
using compose = detail::compose_<Fns...>;
using compose = details::compose_<Fns...>;
/*!
* Create an invocable from other metafunctions by composition.
* \brief
* 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
* type. So for n-ary invocables in the N-1 places the typelist<> is the solution.
* \example
*
* \code
* static_assert( std::is_same<
* invoke<compose_f<F1, F2, F3>, int>, F1 <F2 <F3 <int>>>
@@ -321,12 +389,12 @@ namespace meta{
* \endcode
*/
template <template <typename...> class... Fns>
using compose_f = detail::compose_f_<Fns...>;
using compose_f = details::compose_f_<Fns...>;
//! @}
/*!
* Applies the invocable \p Fn by binding the arguments \p Ts
* to the front of \p Fn.
* \brief
* 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 {
@@ -335,8 +403,8 @@ namespace meta{
};
/*!
* Applies the Invocable \p Fn by binding the arguments \p Ts
* to the back of \p Fn.
* \brief
* 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 {
@@ -362,7 +430,6 @@ namespace meta{
}}
//! @}
//! @}
#endif /* __utl_meta_invoke_h__ */

+ 33
- 19
include/utl/meta/meta.h View File

@@ -1,30 +1,44 @@
/*!
* \file /utl/meta/meta.h
* \brief Include all meta library
* \file utl/meta/meta.h
* \brief Meta library forward header
*/
#ifndef __utl_meta_meta_h__
#define __utl_meta_meta_h__
/*! \defgroup meta Meta
* An embedded metaprogramming library for uTL.
*
* Copyright (C) 2018-2019 Christos Choutouridis
* 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:
*
* 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.
* - 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...
*
* 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.
* All of these operate on integral types.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* - <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
*
* - <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,
* \c push_back, \c at etc...
*/
#ifndef __utl_meta_meta_h__
#define __utl_meta_meta_h__
#include <utl/meta/integral.h>
#include <utl/meta/selection.h>
#include <utl/meta/operations.h>
#include <utl/meta/useif.h>
#include <utl/meta/basic.h>
#include <utl/meta/sfinae.h>
#include <utl/meta/typelist.h>
#include <utl/meta/detection.h>
#include <utl/meta/invoke.h>


+ 0
- 227
include/utl/meta/operations.h View File

@@ -1,227 +0,0 @@
/*!
* \file operations.h
* \brief Integral constant operations and logical operations
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_operations_h__
#define __utl_meta_operations_h__
#include <utl/core/impl.h>
#include <utl/meta/selection.h>
/*!
* \ingroup meta
* \defgroup logic
* logic operators and type relations support
*/
//! @{
namespace utl {
namespace meta{
/*!
* Logical relation for types
*/
//! @{
//! Negate the *bool* constant parameter
template <bool B>
using not_c = bool_<!B>;
//! not
template<typename _Tp>
using not_ = not_c<_Tp::type::value>;
//! OR implementation
//! @{
namespace detail {
template<typename...> struct _or_;
template<>
struct _or_<> : false_ { };
template<typename _T1>
struct _or_<_T1> : _T1 { };
template<typename _T1, typename _T2>
struct _or_ <_T1, _T2>
: if_<_T1, _T1, _T2> { };
template<typename _T1, typename _T2, typename _T3, typename... _Tn>
struct _or_<_T1, _T2, _T3, _Tn...>
: if_<_T1, _T1, _or_<_T2, _T3, _Tn...>> { };
}
template <typename... _Ts>
using or_ = eval<detail::_or_<_Ts...>>;
//! @}
//! AND implementation
//! @{
namespace detail {
template<typename...> struct _and_;
template<>
struct _and_<>
: true_ { };
template<typename _T1>
struct _and_ <_T1>
: _T1 { };
template<typename _T1, typename _T2>
struct _and_<_T1, _T2>
: if_<_T1, _T2, _T1> { };
template<typename _T1, typename _T2, typename _T3, typename... _Tn>
struct _and_<_T1, _T2, _T3, _Tn...>
: if_<_T1, _and_<_T2, _T3, _Tn...>, _T1> { };
}
template <typename... _Ts>
using and_ = eval<detail::_and_<_Ts...>>;
//! @}
//! same
//! @{
template<typename _T1, typename _T2>
struct same_ : false_ { };
template<typename _Tp>
struct same_ <_Tp, _Tp> : true_ { };
//! @}
//! not same
//! @{
template<typename _T1, typename _T2>
using not_same_ = not_<eval<same_<_T1, _T2>>>;
//! @}
//! @}
}}
//! @}
/*!
* \ingroup meta
* \defgroup integral operators
* Type arithmetic and operators
*/
//! @{
namespace utl {
namespace meta {
/*!
* Math operations
* requires IntegralConstant(_Tp)
*/
//! @{
//! Negation
template <typename _Tp>
using negate = integral_<decltype(-_Tp()), -_Tp()>;
//! Addition
template <typename _Tp1, typename _Tp2>
using add = integral_<
decltype(_Tp1() + _Tp2()),
_Tp1() + _Tp2()
>;
//! Multiplication
template <typename _Tp1, typename _Tp2>
using mult = integral_<
decltype(_Tp2() * _Tp2()),
_Tp1() * _Tp2()
>;
//! Division
template <typename _Tp1, typename _Tp2>
using divide = integral_<
decltype(_Tp2() / _Tp2()),
_Tp1() / _Tp2()
>;
//! Modulo
template <typename _Tp1, typename _Tp2>
using modulo = integral_<
decltype(_Tp1() % _Tp2()),
_Tp1() % _Tp2()
>;
//! Substruction
template <typename _Tp1, typename _Tp2>
using sub = add<_Tp1, negate<_Tp2>>;
//! Increase
template <typename _Tp>
using inc = add<_Tp, int_<1>>;
//! decrease
template <typename _Tp>
using dec = add<_Tp, int_<-1>>;
//! @}
/*!
* Comparison operations
* requires IntegralConstant(_Tp)
*/
//! @{
//! \return a true-valued Integral Constant if _Tp1 and _Tp2 are equal.
template <typename _Tp1, typename _Tp2> using comp_eq = bool_<_Tp1() == _Tp2()>;
//! \return a true-valued Integral Constant if _Tp1 is less than _Tp2.
template <typename _Tp1, typename _Tp2> using comp_lt = bool_<(_Tp1() < _Tp2())>;
//! Not equal
template <typename _Tp1, typename _Tp2> using comp_ne = not_<comp_eq<_Tp1, _Tp2>>;
//! Greater than
template <typename _Tp1, typename _Tp2> using comp_gt = comp_lt <_Tp2, _Tp1>;
//! Less or equal
template <typename _Tp1, typename _Tp2> using comp_le = not_<comp_lt<_Tp2, _Tp1>>;
//! Greater or equal
template <typename _Tp1, typename _Tp2> using comp_ge = not_<comp_lt<_Tp1, _Tp2>>;
//! @}
/*!
* Bitwise operations
* requires IntegralConstant(_Tp)
*/
//! @{
//! \return bitwise not (~) operation of its argument.
template <typename _T> using bitnot_ = integral_<typename _T::value_type, (typename _T::value_type)(~_T())>;
//! \return bitwise and (&) operation of its arguments
template <typename _Tp1, typename _Tp2>
using bitand_ = integral_<decltype(_Tp1() & _Tp2()), _Tp1() & _Tp2()>;
//! \return bitwise or (|) operation of its arguments.
template <typename _Tp1, typename _Tp2>
using bitor_ = integral_<decltype(_Tp1() | _Tp2()), _Tp1() | _Tp2()>;
//! \return bitwise xor (^) operation of its arguments.
template <typename _Tp1, typename _Tp2>
using bitxor_ = integral_<decltype(_Tp1() ^ _Tp2()), _Tp1() ^ _Tp2()>;
//! \return the result of bitwise shift left (<<) operation on _Tp.
template <typename _Tp, typename shift>
using shift_left = integral_<typename _Tp::value_type, (typename _Tp::value_type)(_Tp() << shift())>;
//! \return the result of bitwise shift right (>>) operation on _Tp.
template <typename _Tp, typename shift>
using shift_right = integral_<typename _Tp::value_type, (typename _Tp::value_type)(_Tp() >> shift())>;
//! @}
}}
//!@}
#endif /* __utl_meta_operations_h__ */

+ 0
- 86
include/utl/meta/selection.h View File

@@ -1,86 +0,0 @@
/*!
* \file selection.h
* \brief Template meta-programming type selections.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_selection_h__
#define __utl_meta_selection_h__
#include <utl/core/impl.h>
#include <utl/meta/integral.h>
/*!
* \ingroup meta
* \defgroup type selection
* Type selection support header
*/
//! @{
namespace utl {
namespace meta{
/*!
* Type selection
*/
//! @{
//! if_, if_c
//! @{
namespace detail {
template <bool If, typename...>
struct if_c_ {
using type = nil_; //!< avoid ill formed result
};
template<typename Then>
struct if_c_<true, Then> {
using type = Then;
};
template<typename Then, typename Else>
struct if_c_<true, Then, Else> {
using type = Then;
};
template<typename Then, typename Else>
struct if_c_<false, Then, Else> {
using type = Else;
};
}
//! Select one type or another depending on a compile-time Boolean.
template <bool B, typename... Args>
using if_c = eval<detail::if_c_<B, Args...>>;
//! Select one type or another depending on a compile-time Boolean type
template <typename If, typename... Args>
using if_ = if_c<If::type::value, Args...>;
//! @}
/*!
* Named type selectors
*/
//! @{
//! Select the first type of a type sequence
template <typename T1, typename ...> using first_of = T1;
//! Select the second type of a type sequence
template <typename T1, typename T2, typename ...> using second_of = T2;
//! @}
}}
//! @}
#endif /* __utl_meta_selection_h__ */

+ 38
- 27
include/utl/meta/sfinae.h View File

@@ -1,68 +1,79 @@
/*!
* \file sfinae.h
* \brief Template meta-programming SFINAE helpers
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_sfinae_h__
#define __utl_meta_sfinae_h__
#include <utl/core/impl.h>
#include <utl/meta/basic.h>
#include <type_traits>
/*!
* \ingroup meta
* \defgroup sfinae
* \defgroup sfinae SFINAE
* conditional use support header.
*/
//! @{
namespace utl {
namespace meta {
//! Tool to enable a partial specialization only if a boolean condition is true.
//! \name enable_if from STL
//! @{
//! enable_if, imported from stl
template <bool If, typename _Tp = void> using enable_if = std::enable_if<If, _Tp>;
//! alias template for enable_if
template<bool If, typename _Tp = void> using enable_if_t = eval< enable_if<If, _Tp> >;
//! @}
//! \name when implementation
//! @{
namespace detail {
namespace details {
// template <typename... T>
// struct dev_null { using type = dev_null; }; //< Same as typelist
template <bool If> struct when_ { };
template <> struct when_<true> { using type = void; };
}
//! Tool to enable a partial specialization only if a boolean condition is true.
//! Well formed only if \p If is true
template <bool If>
using when = eval< detail::when_<If> >;
using when = eval< details::when_<If> >;
// //! Well formed only if all of \p Ifs are \c true
// template <bool ...Ifs>
// using when_all = detail::dev_null<
// using when_all = details::dev_null<
// when<Ifs>...
// >;
//! @}
//! enable_if
//! @{
//! 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
>;
//! 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
>;
//! If any type (_T1 or _T2) type resolves to _Ret, else to SFINAE
template <typename T1, typename... Ts>
using use_if_any_t = enable_if_t<
or_<T1, Ts...>::value, T1
>;
//! enable_if, imported from stl
template <bool If, typename _Tp = void> using enable_if = std::enable_if<If, _Tp>;
//! If both type (_T1 and _T2) type resolves to _Ret, else to SFINAE
template <typename T1, typename... Ts>
using use_if_all_t = enable_if_t<
and_<T1, Ts...>::value, T1
>;
//! alias template for enable_if
template<bool If, typename _Tp = void> using enable_if_t = eval< enable_if<If, _Tp> >;
//! @}
}}


+ 127
- 133
include/utl/meta/typelist.h View File

@@ -1,33 +1,42 @@
/*!
* \file typelist.h
* \brief A template parameter "container"
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_typelist_h__
#define __utl_meta_typelist_h__
#include <utl/core/impl.h>
#include <utl/meta/integral.h>
#include <utl/meta/basic.h>
#include <utl/meta/detection.h>
#include <utl/meta/invoke.h>
#include <utl/meta/sfinae.h>
/*!
* \ingroup meta
* \defgroup typelist
* \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
*/
//! @{
@@ -36,30 +45,8 @@ namespace meta {
/*!
* \brief
* A class template that just holds a parameter pack.
*
* The idea came from MPL's sequence concept [\ref link1 1] and from N4115 [\ref link2 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).
* \example
* \code
* using l1 = typelist<int, void*, double, void>;
* l1 a {};
* \endcode
*
* boost::hana [\ref link3 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). So a simple python-like list with some extra vector-like
* element access functionalities and no iterators is good enough(for now).
*
* \anchor link1 [1]: https://www.boost.org/doc/
* \anchor link2 [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html
* \anchor link3 [3]: https://github.com/boostorg/hana
* The \c typelist 's implementation container
* \tparam Ts The \a contained types
*/
template <typename... Ts>
struct typelist {
@@ -102,8 +89,8 @@ namespace meta {
public:
/*!
* Generate typelist<Ts..., Ts..., ...> of size \c N arguments.
* \example
* \code
*
* \code{.cpp}
* static_assert (
* std::is_same<typelist<int, char>::times<2>,
* typelist<int, char, int, char>
@@ -122,8 +109,8 @@ namespace meta {
*
* Complexity \f$ O(1) \f$.
*
* \param List A typelist
* \return The size of the typelist
* \tparam List A typelist
* \return The size of the typelist
*/
template <typename List>
using size = size_<List::size()>;
@@ -133,8 +120,8 @@ namespace meta {
*
* Complexity \f$ O(1) \f$.
*
* \param List A typelist
* \return Empty or not
* \tparam List A typelist
* \return Empty or not
*/
template <typename List>
using empty = bool_<List::empty()>;
@@ -145,24 +132,24 @@ namespace meta {
using pair = typelist<T1, T2>;
//! repeat
//! \name repeat
//! @{
/*!
* A wrapper to typelist<>::times<> utility for integer argument \p N
* A wrapper to typelist<>::times<> utility for integer argument \c N
*/
template <size_t N, typename ...Ts>
using repeat_c = typename typelist<Ts...>::template times<N>;
/*!
* A wrapper to typelist<>::times<> utility for integral_c argument \p N
* A wrapper to typelist<>::times<> utility for integral_c argument \c N
*/
template <typename N, typename ...Ts>
using repeat = repeat_c<N::type::value, Ts...>;
//! @}
/*!
* Apply
* \name Apply
* An analogous to apply() implementation for tuples. We just use
* Our typelist<> and integer_sequence<> types.
*/
@@ -171,12 +158,12 @@ namespace meta {
template <typename Fn, typename Seq>
struct apply_ { };
//! \p Sequence == typelist<>
// 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>...>;
@@ -184,14 +171,13 @@ namespace meta {
}
/*!
* Apply the Invocable \p Fn using the types in the type \p Seq as arguments.
* \brief
* 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 \p Seq == typelist<> then
* Unpack typelist and apply to \c Fn
* It \p 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 \n
* 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>;
@@ -204,7 +190,7 @@ namespace meta {
/*
* ========= element access ========
*/
//! at: random element access
//! \name random element access
//! @{
namespace at_impl {
@@ -235,7 +221,7 @@ namespace meta {
}
/*!
* Return the \p N th element in the \c meta::typelist \p List.
* Return the \c N th element in the \c meta::typelist \c List.
*
* Complexity \f$ O(logN) \f$.
*/
@@ -245,16 +231,16 @@ namespace meta {
>;
/*!
* Return the \p N th element in the \c meta::typelist \p List.
* Return the \c N th element in the \c meta::typelist \c List.
*
* Complexity \f$ O(N) \f$.
* Complexity \f$ O(logN) \f$.
*/
template <typename List, typename N>
using at = at_c<List, N::type::value>;
//!@}
//! front
//! \name front
//! @{
namespace front_impl {
template <typename L>
@@ -266,7 +252,8 @@ namespace meta {
};
}
//! Return the first element in \c meta::typelist \p List.
//! Return the first element in \c meta::typelist \c List.
//!
//! Complexity \f$ O(1) \f$.
template <typename List>
using front = eval<
@@ -274,7 +261,7 @@ namespace meta {
>;
//! @}
//! back
//! \name back
//! @{
namespace back_impl {
template <typename List>
@@ -288,7 +275,8 @@ namespace meta {
};
}
//! Return the last element in \c meta::typelist \p List.
//! Return the last element in \c meta::typelist \c List.
//!
//! Complexity \f$ O(N) \f$.
template <typename List>
using back = eval<
@@ -299,7 +287,7 @@ namespace meta {
* ========= typelist operations =========
*/
//! Concatenation
//! \name Concatenation
//! @{
namespace cat_impl {
template <typename... Lists>
@@ -329,8 +317,9 @@ namespace meta {
/*!
* Transformation that concatenates several lists into a single typelist.
* The parameters must all be instantiations of \c meta::typelist.
*
* Complexity: \f$ O(N) \f$
* where \f$ N \f$ is the number of lists passed to the algorithm.
* where \f$ N \f$ is the number of lists passed to the algorithm.
*/
template <typename... Lists>
using cat = eval<
@@ -339,7 +328,7 @@ namespace meta {
//! @}
//! fold<List, V, Fn>, rev_fold<List, V, Fn>
//! \name Fold
//! @{
namespace fold_impl {
// fold<<T1, T2, T3>, V, F> == F<F<F<V, T1>, T2>, T3>
@@ -368,16 +357,17 @@ namespace meta {
}
/*!
* transform the \p List to a new one by doing a left fold using binary Invocable \p Fn
* and initial value \p V
* transform the \c List to a new one by doing a left fold using binary Invocable \c Fn
* and initial value \c V
*
* Complexity \f$ O(N) \f$
* \example
* \code{.cpp}
* fold<typelist<T1, T2, T3>, V, F> == F<F<F<V, T1>, T2>, T3>
* \example
* fold<typelist<>, V, F> == V
* \param List The list to fold
* \param V The initial item feeded to Fn
* \param Fn The binary Invocable
* \endcode
* \tparam List The list to fold
* \tparam V The initial item feeded to Fn
* \tparam Fn The binary Invocable
*/
template <typename List, typename V, typename Fn>
using fold = eval<fold_impl::fold_<List, V, Fn>>;
@@ -421,16 +411,17 @@ namespace meta {
}
/*!
* transform the \p List to a new one by doing a right fold using binary Invocable \p Fn
* and initial value \p V
* transform the \c List to a new one by doing a right fold using binary Invocable \c Fn
* and initial value \c V
*
* Complexity \f$ O(N) \f$
* \example
* \code{.cpp}
* rev_fold<typelist<T1, T2, T3>, V, F> == F<T1, F<T2, F<T3, V>>>
* \example
* rev_fold<typelist<>, V, F> == V
* \param List The list to fold
* \param V The initial item fed to Fn
* \param Fn The binary Invocable
* \endcode
* \tparam List The list to fold
* \tparam V The initial item fed to Fn
* \tparam Fn The binary Invocable
*/
template <typename List, typename V, typename Fn>
using rev_fold = eval<
@@ -439,7 +430,8 @@ namespace meta {
//! @}
/*!
* Return a new \c typelist by adding the elements \p Ts to the front of \p List.
* Return a new \c typelist by adding the elements \c Ts to the front of \c List.
*
* Complexity \f$ O(1) \f$
*/
template <typename List, typename... Ts>
@@ -450,7 +442,8 @@ namespace meta {
>;
/*!
* Return a new \c typelist by adding the elements \p Ts to the back of \p List.
* Return a new \c typelist by adding the elements \c Ts to the back of \c List.
*
* Complexity \f$ O(1) \f$
*/
template <typename List, typename... Ts>
@@ -460,7 +453,7 @@ namespace meta {
>
>;
//! reverse
//! \name reverse
//! @{
namespace reverse_impl {
template <typename List, typename V = typelist<>>
@@ -470,7 +463,8 @@ namespace meta {
}
/*!
* Return a new \c typelist by reversing the elements in the list \p List.
* Return a new \c typelist by reversing the elements in the list \c List.
*
* Complexity \f$ O(N) \f$
*/
template <typename List>
@@ -479,7 +473,7 @@ namespace meta {
>;
//! @}
//! pop_front
//! \name pop_front
//! @{
namespace pop_front_impl {
template <typename List>
@@ -493,7 +487,8 @@ namespace meta {
/*!
* Return a new \c typelist by removing the first element from the
* front of \p List.
* front of \c List.
*
* Complexity \f$ O(1) \f$
*/
template <typename List>
@@ -502,7 +497,7 @@ namespace meta {
>;
//! @}
//! pop_back
//! \name pop_back
//! @{
namespace pop_back_impl {
template <typename List>
@@ -514,7 +509,8 @@ namespace meta {
}
/*!
* Return a new \c typelist by removing the last element from the \p List.
* Return a new \c typelist by removing the last element from the \c List.
*
* Complexity \f$ O(N) \f$.
* \note
* This operation, in addition from other push/pop operations, is
@@ -526,7 +522,7 @@ namespace meta {
>;
//! @}
//! Transform
//! \name Transform
//! @{
namespace transform_impl {
template <typename, typename = void>
@@ -554,8 +550,7 @@ namespace meta {
* and return the resulting typelist
*
* Complexity \f$ O(N) \f$.
* \example
* \code
* \code{.cpp}
* using l1 = typelist<char, int, ...>;
* using l2 = typelist<void, double, ...>;
* using r1 = transform<l1, F1>; // F1, unary invocable
@@ -568,7 +563,7 @@ namespace meta {
>;
//! @}
//! Transform lazy
//! \name Transform lazy
//! @{
namespace transform_lazy_impl {
template <typename, typename = void>
@@ -600,8 +595,7 @@ namespace meta {
*
* Complexity \f$ O(N) \f$
*
* \example
* \code
* \code{.cpp}
* using l1 = typelist<char, int, ...>;
* using l2 = typelist<void, void, ...>;
* using r1 = transform<l1, F1>; // F1, unary invocable
@@ -615,7 +609,7 @@ namespace meta {
//! @}
//! find_if, find
//! \name find_if, find
//! @{
namespace find_if_impl {
template <typename, typename, index_t>
@@ -641,13 +635,13 @@ namespace meta {
}
/*!
* Search for the first \c Item on the \p List for which the predicate \p Pred
* Search for the first \c Item on the \c List for which the predicate \c Pred
* returns true_ when `eval<invoke<Pred, Item>>`
*
* Complexity \f$ O(N) \f$
*
* \param List A typelist
* \param Pred A Unary invocable predicate
* \tparam List A typelist
* \tparam Pred A Unary invocable predicate
* \return An integral constant of index_t with the location of the first match,
* or Npos otherwise.
*/
@@ -657,13 +651,13 @@ namespace meta {
>;
/*!
* Search for the first occurrence of type \p T on a \p List
* Search for the first occurrence of type \c T on a \c List
*/
template <typename List, typename T>
using find = find_if<List, same_as<T>>;
//! @}
//! seek_if
//! \name seek_if
//! @{
namespace seek_if_impl {
template <typename, typename, index_t>
@@ -689,14 +683,14 @@ namespace meta {
}
/*!
* Search for the first \c Item on the \p List for which the predicate \p Pred
* returns true_ when `eval<invoke<Pred, Item>>` and return the rest of the \p List
* Search for the first \c Item on the \c List for which the predicate \c Pred
* 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$
*
* \param List A typelist
* \param Pred A Unary invocable predicate
* \tparam List A typelist
* \tparam Pred A Unary invocable predicate
* \return An integral constant with the location of the first match, on Npos otherwise
*/
template <typename List, typename Pred>
@@ -704,14 +698,14 @@ namespace meta {
seek_if_impl::seek_if_<List, Pred, 0>
>;
/*!
* Search for the first \c Item on the \p List of type \p T and return the rest
* of the \p List starting from that position as new typelist
* Search for the first \c Item on the \c List of type \c T and return the rest
* of the \c List starting from that position as new typelist
*/
template <typename List, typename T>
using seek = seek_if <List, same_as<T>>;
//! @}
//! count_if
//! \name count_if
//! @{
namespace count_if_impl {
template <typename, typename, size_t>
@@ -740,13 +734,13 @@ namespace meta {
}
/*!
* Count all \c Items on the \p List for which the predicate \p Pred
* Count all \c Items on the \c List for which the predicate \c Pred
* returns true_ when `eval<invoke<Pred, Item>>`
*
* Complexity \f$ O(N) \f$
*
* \param List A typelist
* \param Pred A Unary invocable predicate
* \tparam List A typelist
* \tparam Pred A Unary invocable predicate
* \return The total count of occurrences as an integral constant of size_t
*/
template <typename List, typename Pred>
@@ -755,13 +749,13 @@ namespace meta {
>;
/*!
* Count all occurrences of type \p T int \p List
* Count all occurrences of type \c T int \c List
*/
template <typename List, typename T>
using count = count_if<List, same_as<T>>;
//! @}
//! filter
//! \name filter
//! @{
namespace filter_impl {
template <typename, typename, typename>
@@ -786,13 +780,13 @@ namespace meta {
}
/*!
* Return a new typelist with elements, the elements of \p List that satisfy the
* invocable \p Pred such that `eval<invoke<Pred, Item>>` is \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$
*
* \param List The input typelist
* \param Pred A unary invocable predicate
* \tparam List The input typelist
* \tparam Pred A unary invocable predicate
*/
template <typename List, typename Pred>
using filter = eval<
@@ -800,7 +794,7 @@ namespace meta {
>;
//! @}
//! replace
//! \name replace
//! @{
namespace replace_if_impl {
template <typename, typename, typename, typename>
@@ -825,14 +819,14 @@ namespace meta {
}
/*!
* Return a new typelist where all the instances for which the invocation of\p Pred
* returns \c true_, are replaced with \p T
* Return a new typelist where all the instances for which the invocation of\c Pred
* returns \c true_, are replaced with \c T
*
* Complexity \f$ O(N) \f$
*
* \param List The input typelist
* \param Pred A unary invocable predicate
* \param T The new type to replace the item of the \p List, when eval<invoke<Pred, Item>>
* \tparam List The input typelist
* \tparam Pred A unary invocable predicate
* \tparam T The new type to replace the item of the \c List, when eval<invoke<Pred, Item>>
* returns \c true_
*/
template<typename List, typename Pred, typename T>
@@ -840,8 +834,8 @@ namespace meta {
replace_if_impl::replace_if_<List, Pred, T, typelist<>>
>;
//! Alias wrapper that returns a new \c typelist where all instances of type \p T have
//! been replaced with \p U.
//! Alias wrapper that returns a new \c typelist where all instances of type \c T have
//! been replaced with \c U.
template <typename List, typename T, typename U>
using replace = eval <
replace_if <List, same_as<T>, U>
@@ -849,8 +843,8 @@ namespace meta {
//! @}
//! Returns \c true_ if \p Pred returns \c true_ for all the elements in the \p List or if the
//! \p List is empty and \c false_ otherwise.
//! Returns \c true_ if \c Pred returns \c true_ for all the elements in the \c List or if the
//! \c List is empty and \c false_ otherwise.
template <typename List, typename Pred>
using all_of = if_ <
empty <List>,
@@ -860,15 +854,15 @@ namespace meta {
>
>;
//! Returns \c true_ if \p Pred returns \c true_ for any of the elements in the \p List
//! Returns \c true_ if \c Pred returns \c true_ for any of the elements in the \c List
//! and \c false_ otherwise.
template <typename List, typename Pred>
using any_of = not_<
empty<filter <List, Pred>>
>;
//! Returns \c true_ if \p Pred returns \c false_ for all the elements in the \p List
//! or if the \p List is empty and \c false otherwise.
//! Returns \c true_ if \c Pred returns \c false_ for all the elements in the \c List
//! or if the \c List is empty and \c false otherwise.
template <typename List, typename Pred>
using none_of = empty<
filter <List, Pred>


+ 0
- 62
include/utl/meta/useif.h View File

@@ -1,62 +0,0 @@
/*!
* \file useif.h
* \brief Template meta-programming SFINAE 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_meta_useif_h__
#define __utl_meta_useif_h__
#include <utl/core/impl.h>
#include <utl/meta/operations.h>
#include <utl/meta/sfinae.h>
/*!
* \ingroup meta
* \defgroup sfinae
* conditional use support header. This is a SFINAE wrapper
*/
//! @{
namespace utl {
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
>;
//! 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
>;
//! If any type (_T1 or _T2) type resolves to _Ret, else to SFINAE
template <typename T1, typename... Ts>
using use_if_any_t = enable_if_t<
or_<T1, Ts...>::value, T1
>;
//! If both type (_T1 and _T2) type resolves to _Ret, else to SFINAE
template <typename T1, typename... Ts>
using use_if_all_t = enable_if_t<
and_<T1, Ts...>::value, T1
>;
}}
//! @}
#endif /* __utl_meta_useif_h__ */

+ 78
- 37
include/utl/utility/invoke.h View File

@@ -1,21 +1,6 @@
/*!
* \file utl/utility/invoke.h
* \brief invoke() and invoke traits implementation
*
* 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 detail.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __utl_utility_invoke_h__
#define __utl_utility_invoke_h__
@@ -27,13 +12,16 @@
#include <functional>
#include <utility>
//! \defgroup utility Utility
/*!
* \ingroup utility
* \defgroup invoke
* \defgroup util_invoke Invoke
*/
//! @{
namespace utl {
#if !defined __cpp_lib_is_invocable
namespace detail {
template <class T>
@@ -116,16 +104,41 @@ namespace utl {
} // namespace detail
//! Invoke a callable object (for C++14)
template<typename _Callable, typename... _Args>
inline decltype(auto) invoke(_Callable&& fn, _Args&&... args) {
//! 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) {
return detail::invoke_impl_(
std::forward<_Callable>(fn), std::forward<_Args>(args)...
std::forward<Callable>(fn), std::forward<Args>(args)...
);
}
//! @}
//! std::is_invocable trait for C++11
//!
//! \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
template <typename F, typename... Args>
struct is_invocable :
std::is_constructible<
@@ -133,7 +146,19 @@ namespace utl {
std::reference_wrapper<typename std::remove_reference<F>::type>
> { };
//! std::is_invocable_r trait for C++11
//! \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
template <typename R, typename F, typename... Args>
struct is_invocable_r :
std::is_constructible<
@@ -146,38 +171,54 @@ 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...
>;
};
}
//! invoke_result (for C++14)
template <typename _Callable, typename... _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>
using invoke_result = detail::invoke_result_<
is_invocable<_Callable, _Args...>::value,
_Callable,
_Args...
is_invocable<Callable, Args...>::value,
Callable,
Args...
>;
//! invoke_result_t (for C++14)
template<typename _Callable, typename... _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>
using invoke_result_t = meta::eval <
invoke_result<_Callable, _Args...>
invoke_result<Callable, Args...>
>;
//! @}
#else
#endif
}
//! @}


Loading…
Cancel
Save