Compare commits
10 commits
49e7b31511
...
6c079839c2
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c079839c2 | |||
| 17ee3ac1cb | |||
| 20f3252892 | |||
| 2cd3e95228 | |||
| b6a39fa831 | |||
| bad4827b34 | |||
| 170b68ac5c | |||
| 3a5bbd8fb4 | |||
| 3a1f64ec41 | |||
| bb0b73e2a7 |
187 changed files with 3500 additions and 1809 deletions
2
README
2
README
|
|
@ -1,6 +1,6 @@
|
|||
Lumiera -- the video NLE for Linux
|
||||
====================================
|
||||
Version: 0.pre.03
|
||||
Version: 0.pre.04~rc.1
|
||||
:Date: 11/2015
|
||||
|
||||
*************************************************************
|
||||
|
|
|
|||
145
admin/buildVersion.py
Executable file
145
admin/buildVersion.py
Executable file
|
|
@ -0,0 +1,145 @@
|
|||
#!/usr/bin/python3
|
||||
# coding: utf-8
|
||||
##
|
||||
## buildVersion.py - extract and possibly bump current version from Git
|
||||
##
|
||||
|
||||
# Copyright (C)
|
||||
# 2025, Hermann Vosseler <Ichthyostega@web.de>
|
||||
#
|
||||
# **Lumiera** is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2 of the License, or (at your
|
||||
# option) any later version. See the file COPYING for further details.
|
||||
#####################################################################
|
||||
'''
|
||||
Build and possibly bump a current project version spec,
|
||||
based on the nearest Git tag.
|
||||
'''
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
#------------CONFIGURATION----------------------------
|
||||
CMDNAME = os.path.basename(__file__)
|
||||
TAG_PAT = 'v*.*'
|
||||
VER_SEP = r'(?:^v?|\.)'
|
||||
VER_NUM = r'(\w[\w\+]*)'
|
||||
VER_SUB = r'(?:'+VER_SEP+VER_NUM+')'
|
||||
VER_SUF = r'(?:~('+VER_NUM+VER_SUB+'?'+'))'
|
||||
VER_SYNTAX = VER_SUB +VER_SUB+'?' +VER_SUB+'?' +VER_SUF+'?'
|
||||
GIT = 'git'
|
||||
#------------CONFIGURATION----------------------------
|
||||
|
||||
|
||||
|
||||
def parseAndBuild():
|
||||
''' main: parse cmdline and generate version string '''
|
||||
parser = argparse.ArgumentParser (prog=CMDNAME, description='%s: %s' % (CMDNAME, __doc__)
|
||||
,formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
|
||||
parser.add_argument ('--bump','-b'
|
||||
,nargs='?'
|
||||
,choices=['maj','min','rev'], const='rev'
|
||||
,help='bump the version detected from Git (optionally bump a specific component)')
|
||||
parser.add_argument ('--suffix','-s'
|
||||
,help='append (or replace) a suffix (by default attached with ~)')
|
||||
parser.add_argument ('--snapshot'
|
||||
,action='store_true'
|
||||
,help='mark as development snapshot by appending ~dev.YYYYMMDDhhmm, using UTC date from HEAD commit')
|
||||
|
||||
opts = parser.parse_args()
|
||||
|
||||
version = getVersionFromGit()
|
||||
version = rebuild (version, **vars(opts))
|
||||
print (version)
|
||||
|
||||
|
||||
def getVersionFromGit():
|
||||
get_nearest_matching_tag = 'describe --tags --abbrev=0 --match=' + TAG_PAT
|
||||
return runGit (get_nearest_matching_tag)
|
||||
|
||||
def getTimestampFromGit():
|
||||
get_head_author_date = 'show -s --format=%ai'
|
||||
timespec = runGit (get_head_author_date)
|
||||
timespec = datetime.datetime.fromisoformat (timespec)
|
||||
timespec = timespec.astimezone (datetime.timezone.utc) # note: convert into UTC
|
||||
return timespec.strftime ('%Y%m%d%H%M')
|
||||
|
||||
|
||||
|
||||
def rebuild (version, bump=None, suffix=None, snapshot=False):
|
||||
mat = re.fullmatch (VER_SYNTAX, version)
|
||||
if not mat:
|
||||
__FAIL ('invalid version syntax in "'+version+'"')
|
||||
|
||||
maj = mat.group(1)
|
||||
min = mat.group(2)
|
||||
rev = mat.group(3)
|
||||
suf = mat.group(4)
|
||||
suf_idi = mat.group(5) # detail structure not used (as of 2025)
|
||||
suf_num = mat.group(6)
|
||||
|
||||
if bump=='maj':
|
||||
maj = bumpedNum(maj)
|
||||
min = None
|
||||
rev = None
|
||||
elif bump=='min':
|
||||
min = bumpedNum(min)
|
||||
rev = None
|
||||
elif bump=='rev':
|
||||
rev = bumpedNum(rev)
|
||||
|
||||
if snapshot:
|
||||
suf = 'dev.'+getTimestampFromGit()
|
||||
elif suffix:
|
||||
suf = suffix
|
||||
|
||||
version = maj
|
||||
if min:
|
||||
version += '.'+min
|
||||
elif not min and rev:
|
||||
version += '.0'
|
||||
if rev:
|
||||
version += '.'+rev
|
||||
if suf:
|
||||
version += '~'+suf
|
||||
return version
|
||||
|
||||
|
||||
|
||||
def bumpedNum (verStr):
|
||||
mat = re.match (r'\d+', str(verStr))
|
||||
if not mat:
|
||||
return '1'
|
||||
numStr = mat.group(0)
|
||||
num = int(numStr) + 1
|
||||
return str(num).zfill(len(numStr))
|
||||
|
||||
|
||||
def runGit (argStr):
|
||||
''' run Git as system command without shell and retrieve the output '''
|
||||
argList = [GIT] + argStr.split()
|
||||
try:
|
||||
proc = subprocess.run (argList, check=True, capture_output=True, encoding='utf-8', env={'LC_ALL':'C'})
|
||||
return proc.stdout.rstrip() # Note: sanitised env
|
||||
except:
|
||||
__FAIL ('invoking git-describe')
|
||||
|
||||
|
||||
|
||||
|
||||
def __ERR (*args, **kwargs):
|
||||
print (*args, file=sys.stderr, **kwargs)
|
||||
|
||||
def __FAIL (msg):
|
||||
__ERR ("FAILURE: "+msg)
|
||||
exit (-1)
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
parseAndBuild()
|
||||
|
|
@ -22,7 +22,7 @@ import Options
|
|||
|
||||
#-------------------------------------------------------Configuration
|
||||
TARGDIR = 'target'
|
||||
VERSION = '0.pre.03'
|
||||
VERSION = '0.pre.04~rc.1'
|
||||
TOOLDIR = './admin/scons' # SCons plugins
|
||||
OPTCACHE = 'optcache'
|
||||
CUSTOPTFILE = 'custom-options'
|
||||
|
|
|
|||
44
admin/setVersion
Executable file
44
admin/setVersion
Executable file
|
|
@ -0,0 +1,44 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# setVersion - place the version info given as argument
|
||||
# into all the necessary places in the Lumiera tree
|
||||
#
|
||||
#
|
||||
set -e
|
||||
|
||||
function fail() {
|
||||
echo -e "\nFAIL: $1\n\n"
|
||||
exit -1
|
||||
}
|
||||
|
||||
PROJ_ROOT=$(git rev-parse --show-toplevel)
|
||||
cd $PROJ_ROOT
|
||||
[ $# -eq 1 ] || fail "need version as argument\n\nsetVersion <ver>"
|
||||
[ -n "$1" ] || fail "need a nonemty version spec"
|
||||
VER="$1"
|
||||
|
||||
function rewrite() {
|
||||
# Process the indicated file with sed and replace the existing version spec
|
||||
# The PREFIX argument must match everything from line start before the version;
|
||||
# then the _remainder_ of this line will be replaced by the NEWVER
|
||||
FILE="$1"
|
||||
PREFIX="$2"
|
||||
NEWVER="$3"
|
||||
echo "rewrite..... $FILE"
|
||||
egrep -q "^$PREFIX" $FILE || fail "not found in $FILE : $PREFIX"
|
||||
#
|
||||
sed -r -f - -i "$FILE" <<END_SCRIPT
|
||||
/^$PREFIX/ {
|
||||
s/(^$PREFIX).+/\1 $NEWVER/
|
||||
}
|
||||
END_SCRIPT
|
||||
}
|
||||
|
||||
|
||||
rewrite data/config/setup.ini 'version\s*=' "$VER"
|
||||
rewrite doc/devel/Doxyfile 'PROJECT_NUMBER\s*=' "$VER"
|
||||
rewrite doc/devel/Doxyfile.browse 'PROJECT_NUMBER\s*=' "$VER"
|
||||
rewrite admin/scons/Setup.py 'VERSION\s*=' "\'$VER\'"
|
||||
rewrite README 'Version:' "$VER"
|
||||
|
||||
echo -e "\nSUCCESSFULLY rewritten version $VER\ncheck git diff\n\n"
|
||||
|
|
@ -12,7 +12,7 @@ gui = gtk_gui.lum
|
|||
modulepath = $ORIGIN/modules
|
||||
configpath = $ORIGIN/../../share/lumiera/config:$ORIGIN/config:~/.lumiera # currently unused (2/2011)
|
||||
title = Lumiera
|
||||
version = 0.pre.03
|
||||
version = 0.pre.04~rc.1
|
||||
website = http://www.lumiera.org
|
||||
authors = Joel Holdsworth|Christian Thäter|Hermann Voßeler|Stefan Kangas|Michael Fisher|Michael Ploujnikov|and others...
|
||||
copyright = 2007 - 2025
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = Lumiera
|
||||
PROJECT_NUMBER = 0.pre.03
|
||||
PROJECT_NUMBER = 0.pre.04~rc.1
|
||||
PROJECT_BRIEF = "»edit your freedom«"
|
||||
PROJECT_LOGO = draw/rendered/LumiLogo-small.png
|
||||
OUTPUT_DIRECTORY =
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = Lumiera
|
||||
PROJECT_NUMBER = 0.pre.03
|
||||
PROJECT_NUMBER = 0.pre.04~rc.1
|
||||
PROJECT_LOGO = draw/rendered/LumiLogo-small.png
|
||||
OUTPUT_DIRECTORY =
|
||||
CREATE_SUBDIRS = NO
|
||||
|
|
|
|||
213
doc/technical/code/GitBranching.txt
Normal file
213
doc/technical/code/GitBranching.txt
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
Git-flow branching pattern
|
||||
==========================
|
||||
:Date: Summer 2025
|
||||
:toc:
|
||||
:toclevels: 3
|
||||
|
||||
_Lumiera uses Git-flow for branching and release organisation_
|
||||
|
||||
.Motivation
|
||||
Lumiera is a large project with an elaborate structure.
|
||||
Development and integration efforts, refactorings, releases and bugfixes require some degree
|
||||
of coordination -- to avoid confusion, collisions and wasted effort. Git is a flexible tool
|
||||
and can be adapted to a wide array of organisation styles; by means of a time-proven pattern
|
||||
for branches, merges, names and tags, it is possible to represent the activities related to
|
||||
releases and bugfixes directly as structure in the Git history, without much need for explicit
|
||||
release planning, coordination and management.
|
||||
|
||||
TIP: The principles and procedures of *Git-flow* are explained in this
|
||||
->{nbsp}{l}/project/background/GitFlow.html[Background Article]. First
|
||||
link:https://nvie.com/posts/a-successful-git-branching-model/[published in 2010]
|
||||
by _Vincent Driessen_, meanwhile it is widely applied in projects with regular releases
|
||||
and external liabilities -- and often seen as the counterpoint to trunk centred
|
||||
development and continuous delivery.
|
||||
|
||||
|
||||
The Framework
|
||||
-------------
|
||||
The actual entity maintained in Git repositories is _a history line,_ leading to a _Head._
|
||||
Developers collaborate by pulling the history from _some other repository,_ extending or
|
||||
remoulding this history by adding some changes as _commits_ and finally they publish this
|
||||
extended line into their _personal repository._ However, the _normative state_ of the project
|
||||
is represented by the link:https://git.lumiera.org/gitweb?p=LUMIERA[»Lumiera Repository«]
|
||||
`git://git.lumiera.org/LUMIERA`
|
||||
|
||||
The Core Developer(s) can _push_ to this repository, thereby acting as _Gateway._ Automated builds
|
||||
will listen to this repository, and any further _downstream processes,_ like e.g. packaging,
|
||||
are always based on this state. What is described in the following sections however is a
|
||||
_pattern of naming and branch organisation_ -- and can be seen as orthogonal to the former:
|
||||
A structure of branches and tags is assembled, gradually, in some repository; yet whenever the
|
||||
Core Developer(s) push this state to the Lumiera Repository, this structure becomes the
|
||||
normative state of the project. A release happens when the release tag is published this way.
|
||||
|
||||
Development and Production
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The development is the source of _change._ It builds the application, creates new functionality,
|
||||
maintains and evolves the structure of the code. On the other side, the productive use of the
|
||||
application requires _stability._ Users must be confident that they can rely on Lumiera for
|
||||
reaching deadlines and to build their long-term work. These two poles are represented by the
|
||||
two permanent branches: The *development mainline* and the *production master*.
|
||||
|
||||
A release process brings change into a stable shape; it is represented by a *release branch*,
|
||||
which originates from development, goes through a vetting process and finally _ends_ with
|
||||
a *release tag* on production master. Urgent *bugfixes* are based on current production
|
||||
master, and released immediately back to production with a *patch tag*.
|
||||
|
||||
Every delivery to production is also *back-merged* into the development mainline one way
|
||||
or another.footnote:[Some fine points to consider here. These back-merges will typically
|
||||
result in merge conflicts, which require manual handling. This is a desired feature,
|
||||
because reconciling the release changes with ongoing development is essential integration
|
||||
work and also supports the knowledge transfer between developers; it is recommended to
|
||||
consult both parties involved to find a long-term solution when resolution becomes
|
||||
complicated. Note however that the version bumping both on development and for the
|
||||
actual release will cause a spurious conflict, which must always be resolved in favour
|
||||
of the version present on the development line. This task can be automated. And finally,
|
||||
when a bugfix happens _while a release is in-flight,_ then the back-merge
|
||||
*must be done to the release branch*, not the development branch -- because we need the
|
||||
bugfix to be present in the next release too. Failure to observe this special rule will
|
||||
cause a *regression*, i.e. loosing the fix with the next regular release.]
|
||||
This is a distinguishing feature of Git-flow and addresses the quite common problem
|
||||
that bugfix work can be lost for the ongoing development.
|
||||
|
||||
Naming Convention
|
||||
~~~~~~~~~~~~~~~~~
|
||||
master::
|
||||
the branch name used for the infinite line of production code
|
||||
integration::
|
||||
the branch name used for the infinite ongoing main line of development
|
||||
v<ver>::
|
||||
naming pattern for version tags; `<ver>` is the version number string
|
||||
(maybe{nbsp}transliterated to make it valid for Git. Notably `'~'` -> `'_'`)
|
||||
rel/<ver>::
|
||||
naming pattern for release branches; `<ver>` is the version number string
|
||||
for the upcoming release. Only a single release branch is allowed at any
|
||||
given time, and will be deleted after the release merge and tag is set.
|
||||
fix/<ver>::
|
||||
naming pattern for bugfix branches; here `<ver>` is the patch version
|
||||
string, usually with an incremented revision component (maj.min.rev).
|
||||
Only a single bugfix branch is allowed at any given time; these
|
||||
branches are also deleted after publishing the fix.
|
||||
dev/<id>::
|
||||
naming pattern for a development or feature branch; `<id>` is an mnemonic
|
||||
identifier, which must be unique at the time while the branch exists.
|
||||
Development branches are transient and must be deleted after _landing_.footnote:[
|
||||
Sometimes a development effort does not succeed -- or is abandoned for various
|
||||
reasons; if this happens, mark the last state with a tag and _delete_ the branch.
|
||||
A well maintained repository should not contain stale branches.]
|
||||
dev/stage dev/steam dev/vault::
|
||||
these development branch names _can_ be used for pre-integration of development
|
||||
within a layer, in a situation where there is a dedicated sub-team and some
|
||||
elaborated yet isolated development is going on.footnote:[As of 2025, this
|
||||
situation is hypothetical; in the early stages of the Lumiera project, we
|
||||
had three developers working in a relatively independent and often quite
|
||||
experimental way, with several further minor contributors. In such a situation,
|
||||
a staged integration can be helpful. Unless the project becomes _very large_
|
||||
eventually, it seems much more likely that long-lived feature branches will
|
||||
be used for changes cross-cutting all layers.]
|
||||
documentation::
|
||||
a special branch which is immediately published to the Lumiera website;
|
||||
the ASCIIDOC sources of user, design and technical docs are kept in-tree
|
||||
and often augmented simultaneously on several branches -- for that reason
|
||||
the currently published documentation might diverge at times, and will
|
||||
typically be re-joined with the development mainline during the convergence
|
||||
phase before a release. This branch can be fast-forwarded and merged,
|
||||
but never be re-wound or rebased.
|
||||
deb::
|
||||
a special _downstream branch_ which carries the debian packaging, as
|
||||
maintained by the Lumiera team and published through the Lumiera DEB depot.
|
||||
This branch is not visible in the Lumiera project repository, but rather
|
||||
published via a special link:https://git.lumiera.org/gitweb?p=debian/lumiera[DEB repository].
|
||||
<email>/<branch>_signature::
|
||||
GPG signed tags from the Core Developer(s); these tags are frequently force-reset
|
||||
to a new position, and indicate that this branch position was reviewed and
|
||||
approved.footnote:[The relevance of such an ongoing reveiw and trust marker
|
||||
is based in a preference for an open and chaotic approach to development.
|
||||
People may try out things, and collaborate directly. We even maintain a
|
||||
link:https://git.lumiera.org/gitweb?p=lumiera/mob[»Mob repository«]
|
||||
that is _world-pushable_ for small ad-hoc contributions. This option was used
|
||||
indeed, and we never had problems with vandalism. Admittedly, since several
|
||||
years now the ongoing development is way too demanding and esoteric to
|
||||
encourage such low-barrier access, but the vision as such is maintained,
|
||||
hoping to reach a state of the project eventually where direct small-scale
|
||||
contributions will be feasible again (e.g. for plug-ins, configuration,
|
||||
tweaks, styling)]
|
||||
|
||||
Version numbers
|
||||
^^^^^^^^^^^^^^^
|
||||
The link:{rfc}/VersionNumberScheme.html[Version Number scheme of Lumiera]
|
||||
is based on the Debian
|
||||
link:https://www.debian.org/doc/debian-policy/ch-controlfields.html#version[policy for version numbers];
|
||||
note that this policy definition even provides a nice algorithm for version number sorting.
|
||||
In a nutshell, we alternatingly compare non-numeric and numeric parts of version number strings.
|
||||
And `'~'` sorts _before_ anything else, even the empty string, `'+'` sorts before `'.'` and
|
||||
`'-'` (dash) is not allowed, because it is reserved for Debian revisions.
|
||||
|
||||
Notably we have the convention to mark development snapshots with a version number
|
||||
_preceding_ the next expected release, and we do the same with release candiates (`'rc'`);
|
||||
in all those cases, we attach a suffix with a tilde, because this orders _before_ the
|
||||
decorated number: `1.4~dev` comes before `1.4~rc.1` and again before `1.4`
|
||||
|
||||
However, the way we use version tags, a tilde will never show up either on a
|
||||
release branch, nor in the tag itself. These fine distinctions will only be used
|
||||
in the version definition checked into the source tree and picked up by the build
|
||||
system and thus also by the continuous integration.footnote:[as of 2025, we do not
|
||||
have (and do not need yet) a continuous integration; so the actual modus operandi
|
||||
still needs to be figured out.]
|
||||
|
||||
|
||||
Procedures
|
||||
----------
|
||||
Release process
|
||||
~~~~~~~~~~~~~~~
|
||||
What follows is a short summary of the stages and procedures for a release.
|
||||
|
||||
1. Prior to the release, there is a convergence phase
|
||||
- attempt to land features which should be part of the release
|
||||
- stabilise the code and resolve bugs
|
||||
- keep breaking changes on feature branches
|
||||
2. Cut the release, once the code is feature complete
|
||||
- possibly adjust the expected version number based on the current situation
|
||||
- fork the release branch off `integration`, using the expected version number
|
||||
- bump the version number on the `integration` branch, and attach a `~dev` suffix.footnote:[
|
||||
Note there are some scripts in the 'admin' subdirectory to help with version number handling.]
|
||||
3. Get the release code to maturity
|
||||
- additional testing, possibly a public beta
|
||||
- directly fix any bugs encountered on the release branch
|
||||
- avoid any breaking changes and refrain from adding further features
|
||||
- release candidates can be used simply by committing them into the version in-tree;
|
||||
indicate the RC in the commit message, but do not tag them
|
||||
- with the last commit, add the release notes and remove the `~rc` suffix
|
||||
4. Publish the release
|
||||
- merge the release branch into `master` (this will never create a conflict)
|
||||
- set the release tag on this merge commit
|
||||
- publish this state of the history to the Lumiera project repository
|
||||
5. Complete the relase cycle
|
||||
- create a back-merge from the release tag to the `integration` branch
|
||||
- ensure that the integration branch has still the correct verion number, which
|
||||
should be the next one, with a `~dev` suffix.footnote:[...to achieve this, just
|
||||
re-run the script in a similar way as was used to bump the version after forking
|
||||
the release branch.]
|
||||
- resolve any conflicts due to integration of release changes with ongoing development
|
||||
- delete the release branch.
|
||||
|
||||
Bugfixes between Releases
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
1. initiate bugfix
|
||||
- create a bugfix branch from current `master`; include the bugfix number
|
||||
- the first commit on the bugfix branch sets this bugfix number in-tree,
|
||||
thereby typically adding or increasing the revision component of the version
|
||||
2. landing the bugfix
|
||||
- once the problem is resolved and tested, merge back bugfix branch into `master`
|
||||
- merge the bugfix into `integration`
|
||||
- delete the bugfix branch
|
||||
|
||||
Bugfix during Release prep
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
1. initiate bugfix
|
||||
- create a bugfix branch from current `master`; include the bugfix number
|
||||
- use a version _prior_ to the ongoing release, but increment the revision component
|
||||
- commit this bugfix number in-tree
|
||||
2. landing the bugfix
|
||||
- after resolving the problem, merge directly to `master`
|
||||
- be sure to merge the bugfix then *into the release branch*
|
||||
- delete the bugfix branch
|
||||
|
|
@ -2,6 +2,9 @@ Code Base Organisation
|
|||
======================
|
||||
|
||||
//Menu: label Code Base
|
||||
//Menu: prepend child CodingGuidelines
|
||||
//Menu: put child LinkingStructure after CodingGuidelines
|
||||
//Menu: put child GitBranching after LinkingStructure
|
||||
|
||||
|
||||
This section of Lumiera's technical documentation deals with the code base as such,
|
||||
|
|
|
|||
|
|
@ -184,8 +184,44 @@ pick and manipulate individually::
|
|||
can be programmed recursively, similar to LISP. The »bridge« is to unpack the variadic argument pack
|
||||
into the `lib::meta::Types<ARGS...>`
|
||||
+
|
||||
meta-manipulations::
|
||||
When you need to rebind and manipulate a variadic sequence, it helps to transform the sequence
|
||||
into one of our meta sequence representations (`lib::meta::Types` or the Loki typelists).
|
||||
In `variadic-helper.hpp`, we define a convenient rebinding template `lib::meta::Elms<>`,
|
||||
which can work transparently on any type sequence or any tuple-like entity
|
||||
+
|
||||
- to get at the variadics in a sequence representation
|
||||
- to get a matching index sequence
|
||||
- to rebind into another variadic template, using the same variadic sequence
|
||||
- to apply a meta-function on each of the variadic types
|
||||
- to compute a conjunction or disjunction of meta-predicates over the sequence
|
||||
+
|
||||
tuple-like::
|
||||
This is a concept to match on any type in compliance with the »tuple protocol«
|
||||
+
|
||||
- such a type must inject a specialisation of `std::tuple_size<TY>`
|
||||
- and it must likewise support `std::tuple_element_t<N, TY>`
|
||||
- and, based on that, expose a constexpr _getter function_
|
||||
- together this also implies, that such a type can be used in _structured bindings_
|
||||
(but note, structured bindings also work on plain arrays and on simple structs,
|
||||
which are _not_ considered _tuple-like_ by themselves)
|
||||
+
|
||||
apply to tuple-likes::
|
||||
Unfortunately, the standard has a glaring deficiency here, insofar it defines an _exposition only_
|
||||
concept, which is then hard mapped to support only some fixed types from the STL (tuples, pairs,
|
||||
std::array and some range stuff). This was one of the main reasons to define our own `concept tuple_like`
|
||||
+
|
||||
- but unfortunately, `std::apply` was fixed with C++20 to allow only the above mentioned fixed set of
|
||||
types from the STL, while in theory there is no reason why not to allow any _tuple-like_ entity
|
||||
- this forces us to define our own `lib::meta::apply` as a drop-in replacement for `std::apply`
|
||||
- in addition to that, we also define a `lib::meta::getElm<N, TY>`, which is an universal getter
|
||||
to work on any _tuple-like_, either with a `get` member function or a free-ADL function `get`
|
||||
- note that starting with C++20 it is forbidden to inject function overloads into namespace std,
|
||||
and thus a free `get` function must be injected as friend via ADL and used appropriately, i.e.
|
||||
unqualified.
|
||||
+
|
||||
apply functor to each tuple element::
|
||||
A common trick is to use `std::apply` in combination with a _fold-expression_
|
||||
A common trick is to use `apply` in combination with a _fold-expression_
|
||||
+
|
||||
- provided as `lib::meta::forEach` in 'lib/meta/tuple-helper.hpp
|
||||
- The design of the `DataTable` with CSV-Formatting is based on this technique, see 'lib/stat/data.hpp'
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
/** @file try.cpp
|
||||
* Develop a concept to detect _tuple-like_ classes, based on the requirements
|
||||
* of the »tuple protocol«. Using some ideas from [Stackoverflow] as starting point.
|
||||
* However, we model both a _friend function_ `get` and a similar member function
|
||||
* as alternatives for element access, and we break down the checks into sub-concepts.
|
||||
* [Stackoverflow]: https://stackoverflow.com/q/68443804/444796
|
||||
*/
|
||||
|
||||
|
|
@ -27,58 +29,6 @@
|
|||
|
||||
using std::string;
|
||||
|
||||
namespace lib {
|
||||
namespace meta {
|
||||
|
||||
template<class TUP>
|
||||
concept tuple_sized = requires
|
||||
{
|
||||
{ std::tuple_size<TUP>::value } -> std::convertible_to<size_t>;
|
||||
};
|
||||
|
||||
|
||||
template<class TUP, std::size_t N>
|
||||
concept tuple_adl_accessible = requires(TUP tup)
|
||||
{
|
||||
typename std::tuple_element_t<N, TUP>;
|
||||
{ get<N>(tup) } -> std::convertible_to<std::tuple_element_t<N, TUP>&>;
|
||||
};
|
||||
|
||||
template<class TUP, std::size_t N>
|
||||
concept tuple_mem_accessible = requires(TUP tup)
|
||||
{
|
||||
typename std::tuple_element_t<N, TUP>;
|
||||
{ tup.template get<N>() } -> std::convertible_to<std::tuple_element_t<N, TUP>&>;
|
||||
};
|
||||
|
||||
template<class TUP, std::size_t N>
|
||||
concept tuple_accessible = tuple_mem_accessible<TUP,N> or tuple_adl_accessible<TUP,N>;
|
||||
|
||||
template<class TUP>
|
||||
class AndAll
|
||||
{
|
||||
template<size_t...idx>
|
||||
static constexpr bool
|
||||
canAccessAll (std::index_sequence<idx...>)
|
||||
{
|
||||
return (tuple_accessible<TUP, idx> and ...);
|
||||
}
|
||||
|
||||
using IdxSeq = typename ElmTypes<TUP>::Idx;
|
||||
|
||||
public:
|
||||
static constexpr bool can_AccessElement = canAccessAll(IdxSeq{});
|
||||
};
|
||||
|
||||
|
||||
template<class TUP>
|
||||
concept tuple_like = not is_reference_v<TUP>
|
||||
and tuple_sized<remove_cv_t<TUP>>
|
||||
and AndAll<remove_cv_t<TUP>>::can_AccessElement;
|
||||
|
||||
}}//namespace lib::meta
|
||||
|
||||
|
||||
|
||||
template<typename X>
|
||||
void
|
||||
|
|
@ -103,7 +53,7 @@ show()
|
|||
int
|
||||
main (int, char**)
|
||||
{
|
||||
using Tup = std::tuple<long>;
|
||||
using Tup = std::tuple<long,short>;
|
||||
using Arr = std::array<int,3>;
|
||||
using Hetero = lib::HeteroData<int,string>::Chain<short>::ChainExtent<bool,lib::meta::Nil>::ChainType;
|
||||
|
||||
|
|
@ -112,11 +62,11 @@ main (int, char**)
|
|||
SHOW_EXPR((lib::meta::tuple_sized<Hetero> ))
|
||||
SHOW_EXPR((lib::meta::tuple_sized<int> ))
|
||||
|
||||
SHOW_EXPR((lib::meta::tuple_accessible<Tup,0>))
|
||||
// SHOW_EXPR((lib::meta::tuple_accessible<Tup,2>))
|
||||
SHOW_EXPR((lib::meta::tuple_accessible<Hetero,0>))
|
||||
SHOW_EXPR((lib::meta::AndAll<Tup>::can_AccessElement))
|
||||
SHOW_EXPR((lib::meta::AndAll<Hetero>::can_AccessElement))
|
||||
SHOW_EXPR((lib::meta::tuple_element_accessible<Tup,0>))
|
||||
// SHOW_EXPR((lib::meta::tuple_element_accessible<Tup,2>))
|
||||
SHOW_EXPR((lib::meta::tuple_element_accessible<Hetero,0>))
|
||||
SHOW_EXPR((lib::meta::tuple_accessible<Tup>))
|
||||
SHOW_EXPR((lib::meta::tuple_accessible<Hetero>))
|
||||
|
||||
SHOW_EXPR((lib::meta::tuple_like<Tup> ))
|
||||
SHOW_EXPR((lib::meta::tuple_like<Arr> ))
|
||||
|
|
@ -128,9 +78,25 @@ main (int, char**)
|
|||
show<Hetero>();
|
||||
show<int>();
|
||||
|
||||
SHOW_EXPR(bool(std::is_integral_v<int>))
|
||||
SHOW_EXPR(bool(std::is_integral_v<char>))
|
||||
SHOW_EXPR(bool(std::is_integral_v<double>))
|
||||
SHOW_EXPR((std::tuple_size_v<const Tup>))
|
||||
using Elm1 = std::tuple_element_t<1, const Tup>;
|
||||
SHOW_TYPE(Elm1)
|
||||
using TupConstSeq = lib::meta::ElmTypes<const Tup>::Seq;
|
||||
SHOW_TYPE(TupConstSeq)
|
||||
|
||||
using T1 = decltype(lib::meta::getElm<0> (std::declval<Tup>()));
|
||||
SHOW_TYPE(T1)
|
||||
using T2 = decltype(lib::meta::getElm<0> (std::declval<Tup&>()));
|
||||
SHOW_TYPE(T2)
|
||||
using T3 = decltype(lib::meta::getElm<0> (std::declval<Tup const&>()));
|
||||
SHOW_TYPE(T3)
|
||||
|
||||
using H1 = decltype(lib::meta::getElm<4> (std::declval<Hetero>()));
|
||||
SHOW_TYPE(H1)
|
||||
using H2 = decltype(lib::meta::getElm<4> (std::declval<Hetero&>()));
|
||||
SHOW_TYPE(H2)
|
||||
using H3 = decltype(lib::meta::getElm<4> (std::declval<Hetero const&>()));
|
||||
SHOW_TYPE(H3)
|
||||
|
||||
cout << "\n.gulp." <<endl;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
**
|
||||
** This header is intended to be incorporated as part of the advice system implementation (advice.cpp).
|
||||
** It is \em not usable as an external interface. But it is written in a rather self-contained manner,
|
||||
** in order to be testable in isolation. To this end, the actual PointOfAdvice entities being organised
|
||||
** in order to be testable in isolation. To this end, the actual PointOfAdvice entities \a POA organised
|
||||
** by this index datastructure remain abstract (defined as template parameter), and are only manipulated
|
||||
** through the following functions:
|
||||
** - \c hash_value(POA)
|
||||
|
|
@ -87,7 +87,6 @@
|
|||
#include "lib/util.hpp"
|
||||
#include "common/advice/binding.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -122,6 +121,7 @@ namespace advice {
|
|||
* by invoking the \c setSolution() function on the
|
||||
* corresponding PointOfAdvice entity.
|
||||
*
|
||||
* @tparam POA _point-of-advice_ exposing a matcher and solution
|
||||
* @note element \em identity is defined in terms of pointing
|
||||
* to the same memory location of a POA (point of advice).
|
||||
* Thus e.g. #hasProvision means this index holds an entry
|
||||
|
|
@ -141,12 +141,8 @@ namespace advice {
|
|||
class Index
|
||||
{
|
||||
|
||||
|
||||
struct Entry
|
||||
: pair<Binding::Matcher, POA*>
|
||||
, boost::equality_comparable<Entry, POA,
|
||||
boost::equality_comparable<Entry>
|
||||
>
|
||||
{
|
||||
explicit
|
||||
Entry (POA& elm)
|
||||
|
|
@ -175,8 +171,8 @@ namespace advice {
|
|||
};
|
||||
|
||||
|
||||
typedef vector<Entry> EntryList;
|
||||
typedef typename EntryList::iterator EIter;
|
||||
using EntryList = vector<Entry>;
|
||||
using EIter = EntryList::iterator;
|
||||
|
||||
|
||||
struct Cluster
|
||||
|
|
@ -253,7 +249,7 @@ namespace advice {
|
|||
POA*
|
||||
find_latest_solution (POA& requestElm)
|
||||
{
|
||||
typedef typename EntryList::reverse_iterator RIter;
|
||||
using RIter = EntryList::reverse_iterator;
|
||||
Binding::Matcher pattern (requestElm.getMatcher());
|
||||
for (RIter ii=this->elms_.rbegin();
|
||||
ii!=this->elms_.rend();
|
||||
|
|
@ -518,8 +514,8 @@ namespace advice {
|
|||
bool
|
||||
Index<POA>::isValid() const
|
||||
{
|
||||
typedef typename RTable::const_iterator RTIter;
|
||||
typedef typename PTable::const_iterator PTIter;
|
||||
using RTIter = RTable::const_iterator;
|
||||
using PTIter = PTable::const_iterator;
|
||||
|
||||
try {
|
||||
for (PTIter ii =provisionEntries_.begin();
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ namespace lumiera {
|
|||
|
||||
/** The ServiceHandle automatically creates and manages the Proxy instance */
|
||||
template<class I, class FA>
|
||||
using ServiceHandle = typename lib::DependInject<FA>::template ServiceInstance<Proxy<InstanceHandle<I,FA>>>;
|
||||
using ServiceHandle = lib::DependInject<FA>::template ServiceInstance<Proxy<InstanceHandle<I,FA>>>;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <compare>
|
||||
#include <memory>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -136,6 +136,8 @@ namespace lumiera {
|
|||
: kind(k)
|
||||
, type(t)
|
||||
{ }
|
||||
|
||||
auto operator<=> (QueryID const&) const =default;
|
||||
};
|
||||
|
||||
QueryID const&
|
||||
|
|
@ -185,26 +187,6 @@ namespace lumiera {
|
|||
};
|
||||
|
||||
|
||||
inline bool
|
||||
operator< (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
||||
{
|
||||
return id1.kind < id2.kind
|
||||
or(id1.kind == id2.kind and id1.type < id2.type);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator== (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
||||
{
|
||||
return id1.kind == id2.kind
|
||||
and id1.type == id2.type;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
||||
{
|
||||
return not (id1 == id2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
|
@ -386,7 +368,6 @@ namespace lumiera {
|
|||
* Implicitly convertible to and from Query instances.
|
||||
*/
|
||||
class QueryKey
|
||||
: boost::totally_ordered<QueryKey>
|
||||
{
|
||||
Goal::QueryID id_;
|
||||
lib::QueryText def_;
|
||||
|
|
@ -442,21 +423,19 @@ namespace lumiera {
|
|||
}
|
||||
|
||||
|
||||
friend bool
|
||||
operator< (QueryKey const& q1, QueryKey const& q2)
|
||||
friend std::strong_ordering
|
||||
operator<=> (QueryKey const& q1, QueryKey const& q2)
|
||||
{
|
||||
uint d1 = q1.degree();
|
||||
uint d2 = q2.degree();
|
||||
return d1 < d2
|
||||
or(d1 == d2 and ( q1.def_ < q2.def_
|
||||
or (q1.def_ == q2.def_ and q1.id_ < q2.id_)));
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator== (QueryKey const& q1, QueryKey const& q2)
|
||||
{
|
||||
return q1.def_ == q2.def_;
|
||||
if (auto o1 = d1 <=> d2; o1 != 0)
|
||||
return o1;
|
||||
if (auto o2 = q1.def_ <=> q2.def_; o2 != 0)
|
||||
return o2;
|
||||
else
|
||||
return q1.id_ <=> q2.id_;
|
||||
}
|
||||
bool operator== (QueryKey const&) const =default;
|
||||
|
||||
friend size_t
|
||||
hash_value (QueryKey const& q)
|
||||
|
|
@ -559,7 +538,7 @@ namespace lumiera {
|
|||
|
||||
|
||||
template<class RES>
|
||||
inline typename Query<RES>::Builder
|
||||
inline Query<RES>::Builder
|
||||
Query<RES>::build (Kind queryType)
|
||||
{
|
||||
return Builder(defineQueryTypeID (queryType));
|
||||
|
|
@ -567,7 +546,7 @@ namespace lumiera {
|
|||
|
||||
|
||||
template<class RES>
|
||||
inline typename Query<RES>::Builder
|
||||
inline Query<RES>::Builder
|
||||
Query<RES>::rebuild() const
|
||||
{
|
||||
return Builder(this->id_, getQueryDefinition());
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace query {
|
|||
|
||||
/** we maintain an independent defaults registry
|
||||
* for every participating kind of object. */
|
||||
typedef std::vector< P<TableEntry> > Table;
|
||||
using Table = std::vector< P<TableEntry> >;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -132,7 +132,7 @@ namespace query {
|
|||
struct Slot
|
||||
: public TableEntry
|
||||
{
|
||||
typedef std::set<Record<TAR>> Registry;
|
||||
using Registry = std::set<Record<TAR>>;
|
||||
|
||||
Registry registry;
|
||||
static size_t index; ///< where to find this Slot in every Table
|
||||
|
|
@ -194,7 +194,7 @@ namespace query {
|
|||
class Iter
|
||||
{
|
||||
friend class DefsRegistry;
|
||||
typedef typename Slot<TAR>::Registry::iterator II;
|
||||
using II = Slot<TAR>::Registry::iterator;
|
||||
|
||||
II p,i,e;
|
||||
P<TAR> next, ptr;
|
||||
|
|
@ -251,12 +251,12 @@ namespace query {
|
|||
{
|
||||
P<TAR> dummy;
|
||||
Record<TAR> entry (query, dummy);
|
||||
typedef typename Slot<TAR>::Registry Registry;
|
||||
using Registry = Slot<TAR>::Registry;
|
||||
Registry& registry = Slot<TAR>::access(table_);
|
||||
|
||||
// try to get a possible direct match (same query)
|
||||
typename Registry::iterator pos = registry.find (entry);
|
||||
typename Registry::iterator end = registry.end();
|
||||
auto pos = registry.find (entry);
|
||||
auto end = registry.end();
|
||||
|
||||
if (pos==end)
|
||||
return Iter<TAR> (registry.begin(), end); // just enumerate contents
|
||||
|
|
@ -277,8 +277,8 @@ namespace query {
|
|||
put (P<TAR> const& obj, Query<TAR> const& query)
|
||||
{
|
||||
Record<TAR> entry (query, obj);
|
||||
typedef typename Slot<TAR>::Registry Registry;
|
||||
typedef typename Registry::iterator RIter;
|
||||
using Registry = Slot<TAR>::Registry;
|
||||
using RIter = Registry::iterator;
|
||||
|
||||
Registry& registry = Slot<TAR>::access(table_);
|
||||
RIter pos = registry.lower_bound (entry);
|
||||
|
|
@ -306,8 +306,8 @@ namespace query {
|
|||
bool
|
||||
forget (P<TAR> const& obj)
|
||||
{
|
||||
typedef typename Slot<TAR>::Registry Registry;
|
||||
typedef typename Record<TAR>::Search SearchFunc;
|
||||
using Registry = Slot<TAR>::Registry;
|
||||
using SearchFunc = Record<TAR>::Search;
|
||||
|
||||
Registry& registry = Slot<TAR>::access(table_);
|
||||
return util::remove_if(registry, SearchFunc (obj));
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ namespace lumiera {
|
|||
|
||||
|
||||
template<typename RES>
|
||||
inline typename Query<RES>::iterator
|
||||
inline Query<RES>::iterator
|
||||
Query<RES>::resolveBy (QueryResolver const& resolver) const
|
||||
{
|
||||
PReso resultSet = resolver.issue (*this);
|
||||
|
|
@ -150,7 +150,7 @@ namespace lumiera {
|
|||
/** notational convenience shortcut,
|
||||
* synonymous to Query<RES>::resolveBy() */
|
||||
template<typename RES>
|
||||
inline typename Query<RES>::iterator
|
||||
inline Query<RES>::iterator
|
||||
Query<RES>::operator() (QueryResolver const& resolver) const
|
||||
{
|
||||
return resolveBy (resolver);
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ namespace lumiera {
|
|||
using lib::Symbol;
|
||||
|
||||
//defined in liblumiera.so
|
||||
extern const char * ON_BASIC_INIT; ///< automatic static init. treated specially to run as soon as possible
|
||||
extern const char * ON_GLOBAL_INIT; ///< to be triggered in main() @note no magic!
|
||||
extern const char * ON_GLOBAL_SHUTDOWN; ///< to be triggered at the end of main() @note no magic!
|
||||
extern CStr ON_BASIC_INIT; ///< automatic static init. treated specially to run as soon as possible
|
||||
extern CStr ON_GLOBAL_INIT; ///< to be triggered in main() @note no magic!
|
||||
extern CStr ON_GLOBAL_SHUTDOWN; ///< to be triggered at the end of main() @note no magic!
|
||||
|
||||
extern const char * ON_EMERGENCY; ///< activated on shutdown after premature failure of a subsystem
|
||||
extern CStr ON_EMERGENCY; ///< activated on shutdown after premature failure of a subsystem
|
||||
|
||||
|
||||
// client code is free to register and use additional lifecycle events
|
||||
|
|
|
|||
|
|
@ -347,14 +347,14 @@ namespace lib {
|
|||
struct SetupSeveral<std::void_t, lib::AllocationCluster&>
|
||||
{
|
||||
template<typename X>
|
||||
using Adapter = typename AllocationCluster::template Allocator<X>;
|
||||
using Adapter = AllocationCluster::template Allocator<X>;
|
||||
|
||||
template<class I, class E>
|
||||
struct Policy
|
||||
: AllocationPolicy<I,E,Adapter>
|
||||
{
|
||||
using Base = AllocationPolicy<I,E,Adapter>;
|
||||
using Bucket = typename Base::Bucket;
|
||||
using Bucket = Base::Bucket;
|
||||
|
||||
/** @warning allocation size is severely limited in AllocationCluster. */
|
||||
size_t static constexpr ALLOC_LIMIT = AllocationCluster::max_size();
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ namespace lib {
|
|||
{
|
||||
using Allo = ALO;
|
||||
using AlloT = std::allocator_traits<Allo>;
|
||||
using BaseType = typename Allo::value_type;
|
||||
using BaseType = Allo::value_type;
|
||||
|
||||
Allo& baseAllocator() { return *this; }
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ namespace lib {
|
|||
auto
|
||||
adaptAllocator()
|
||||
{
|
||||
using XAllo = typename AlloT::template rebind_alloc<X>;
|
||||
using XAllo = AlloT::template rebind_alloc<X>;
|
||||
if constexpr (std::is_constructible_v<XAllo, Allo>)
|
||||
return XAllo{baseAllocator()};
|
||||
else
|
||||
|
|
@ -105,8 +105,8 @@ namespace lib {
|
|||
}
|
||||
|
||||
template<class ALOT, typename...ARGS>
|
||||
typename ALOT::pointer
|
||||
construct (typename ALOT::allocator_type& allo, ARGS&& ...args)
|
||||
ALOT::pointer
|
||||
construct (ALOT::allocator_type& allo, ARGS&& ...args)
|
||||
{
|
||||
auto loc = ALOT::allocate (allo, 1);
|
||||
try { ALOT::construct (allo, loc, std::forward<ARGS>(args)...); }
|
||||
|
|
@ -120,7 +120,7 @@ namespace lib {
|
|||
|
||||
template<class ALOT>
|
||||
void
|
||||
destroy (typename ALOT::allocator_type& allo, typename ALOT::pointer elm)
|
||||
destroy (ALOT::allocator_type& allo, ALOT::pointer elm)
|
||||
{
|
||||
ALOT::destroy (allo, elm);
|
||||
ALOT::deallocate (allo, elm, 1);
|
||||
|
|
@ -167,7 +167,7 @@ namespace lib {
|
|||
}
|
||||
else
|
||||
{
|
||||
using XAlloT = typename AlloT::template rebind_traits<TY>;
|
||||
using XAlloT = AlloT::template rebind_traits<TY>;
|
||||
auto xAllo = adaptAllocator<TY>();
|
||||
return construct<XAlloT> (xAllo, std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ namespace lib {
|
|||
}
|
||||
else
|
||||
{
|
||||
using XAlloT = typename AlloT::template rebind_traits<TY>;
|
||||
using XAlloT = AlloT::template rebind_traits<TY>;
|
||||
auto xAllo = adaptAllocator<TY>();
|
||||
destroy<XAlloT> (xAllo, elm);
|
||||
}
|
||||
|
|
@ -334,7 +334,7 @@ namespace lib {
|
|||
{
|
||||
storage_.erase (pos); // EX_FREE
|
||||
|
||||
const char* errID = lumiera_error();
|
||||
CStr errID = lumiera_error();
|
||||
ERROR (memory, "Allocation failed with unknown exception. "
|
||||
"Lumiera errorID=%s", errID?errID:"??");
|
||||
throw;
|
||||
|
|
|
|||
|
|
@ -148,8 +148,8 @@ namespace lib {
|
|||
class DependInject
|
||||
: util::NoInstance
|
||||
{
|
||||
using Factory = typename Depend<SRV>::Factory;
|
||||
using Lock = typename Depend<SRV>::Lock;
|
||||
using Factory = Depend<SRV>::Factory;
|
||||
using Lock = Depend<SRV>::Lock;
|
||||
|
||||
public:
|
||||
/** configure dependency-injection for type SRV to build a subclass singleton.
|
||||
|
|
@ -178,8 +178,8 @@ namespace lib {
|
|||
static void
|
||||
useSingleton (FUN&& ctor)
|
||||
{
|
||||
using Sub = typename SubclassFactoryType<FUN>::Subclass;
|
||||
using Fun = typename SubclassFactoryType<FUN>::Functor;
|
||||
using Sub = SubclassFactoryType<FUN>::Subclass;
|
||||
using Fun = SubclassFactoryType<FUN>::Functor;
|
||||
|
||||
__assert_compatible<Sub>();
|
||||
installFactory<Sub,Fun> (forward<FUN> (ctor));
|
||||
|
|
@ -372,9 +372,9 @@ namespace lib {
|
|||
static_assert (meta::_Fun<FUN>(),
|
||||
"Need a Lambda or Function object to create a heap allocated instance");
|
||||
|
||||
using Functor = typename meta::_Fun<FUN>::Functor; // suitable type to store for later invocation
|
||||
using ResultVal = typename meta::_Fun<FUN>::Ret;
|
||||
using Subclass = typename meta::Strip<ResultVal>::TypePlain;
|
||||
using Functor = meta::_Fun<FUN>::Functor; // suitable type to store for later invocation
|
||||
using ResultVal = meta::_Fun<FUN>::Ret;
|
||||
using Subclass = meta::Strip<ResultVal>::TypePlain;
|
||||
|
||||
static_assert (std::is_pointer<ResultVal>::value,
|
||||
"Function must yield a pointer to a heap allocated instance");
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ namespace diff{
|
|||
struct InterpreterScheme ///< base case is to expect typedef I::Val
|
||||
{
|
||||
using Interpreter = I;
|
||||
using Val = typename I::Val;
|
||||
using Val = I::Val;
|
||||
using Handler = HandlerFun<I,Val>;
|
||||
};
|
||||
|
||||
|
|
@ -188,12 +188,12 @@ namespace diff{
|
|||
struct DiffStepBuilder
|
||||
{
|
||||
using Scheme = InterpreterScheme<I>;
|
||||
using Handler = typename Scheme::Handler;
|
||||
using Val = typename Scheme::Val;
|
||||
using Handler = Scheme::Handler;
|
||||
using Val = Scheme::Val;
|
||||
|
||||
using Lang = DiffLanguage<I,Val>;
|
||||
using Step = typename Lang::DiffStep;
|
||||
using Verb = typename Lang::DiffVerb;
|
||||
using Step = Lang::DiffStep;
|
||||
using Verb = Lang::DiffVerb;
|
||||
|
||||
Handler handler;
|
||||
Literal id;
|
||||
|
|
@ -239,7 +239,7 @@ namespace diff{
|
|||
* @warning use for internal state marking only --
|
||||
* invoking this token produces undefined behaviour */
|
||||
template<class I, typename E>
|
||||
const typename DiffLanguage<I,E>::DiffStep DiffLanguage<I,E>::NIL = DiffStep(DiffVerb(), E());
|
||||
const DiffLanguage<I,E>::DiffStep DiffLanguage<I,E>::NIL = DiffStep(DiffVerb(), E());
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ namespace diff{
|
|||
struct RecordSetup<GenNode>
|
||||
{
|
||||
using Storage = std::vector<GenNode>;
|
||||
using ElmIter = typename Storage::const_iterator;
|
||||
using ElmIter = Storage::const_iterator;
|
||||
|
||||
/** using const reference data access
|
||||
* relevant for handling large subtrees */
|
||||
|
|
@ -269,11 +269,11 @@ namespace diff{
|
|||
, data(std::forward<X>(val))
|
||||
{ }
|
||||
|
||||
GenNode(string const& symbolicID, const char* text)
|
||||
GenNode(string const& symbolicID, CStr text)
|
||||
: GenNode(symbolicID, string(text))
|
||||
{ }
|
||||
|
||||
GenNode(const char* text)
|
||||
GenNode(CStr text)
|
||||
: GenNode(string(text))
|
||||
{ }
|
||||
|
||||
|
|
@ -516,7 +516,7 @@ namespace diff{
|
|||
using No = lib::meta::No_t;
|
||||
|
||||
template<class X>
|
||||
static Yes check(typename variant::CanBuildFrom<X, DataValues>::Type*);
|
||||
static Yes check(variant::CanBuildFrom<X, DataValues>::Type*);
|
||||
template<class X>
|
||||
static No check(...);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ namespace diff{
|
|||
|
||||
/* === forwarded sequence access === */
|
||||
|
||||
using iterator = typename std::vector<VAL>::iterator;
|
||||
using const_iterator = typename std::vector<VAL>::const_iterator;
|
||||
using iterator = std::vector<VAL>::iterator;
|
||||
using const_iterator = std::vector<VAL>::const_iterator;
|
||||
|
||||
iterator begin() { return data_.begin(); }
|
||||
iterator end() { return data_.end(); }
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace diff{
|
|||
: public ListDiffInterpreter<E>
|
||||
{
|
||||
using Vec = vector<E,ARGS...>;
|
||||
using Iter = typename Vec::iterator;
|
||||
using Iter = Vec::iterator;
|
||||
|
||||
Vec orig_;
|
||||
Vec& seq_;
|
||||
|
|
|
|||
|
|
@ -78,14 +78,14 @@ namespace diff{
|
|||
class DiffDetector
|
||||
: util::NonCopyable
|
||||
{
|
||||
using Val = typename SEQ::value_type;
|
||||
using Val = SEQ::value_type;
|
||||
using Idx = IndexTable<Val>;
|
||||
|
||||
Idx refIdx_;
|
||||
SEQ const& currentData_;
|
||||
|
||||
|
||||
using DiffStep = typename ListDiffLanguage<Val>::DiffStep;
|
||||
using DiffStep = ListDiffLanguage<Val>::DiffStep;
|
||||
|
||||
/** @internal state frame for diff detection and generation. */
|
||||
class DiffFrame;
|
||||
|
|
|
|||
|
|
@ -140,9 +140,9 @@ namespace diff{
|
|||
template<typename VAL>
|
||||
class Record
|
||||
{
|
||||
using Storage = typename RecordSetup<VAL>::Storage;
|
||||
using ElmIter = typename RecordSetup<VAL>::ElmIter;
|
||||
using Access = typename RecordSetup<VAL>::Access;
|
||||
using Storage = RecordSetup<VAL>::Storage;
|
||||
using ElmIter = RecordSetup<VAL>::ElmIter;
|
||||
using Access = RecordSetup<VAL>::Access;
|
||||
|
||||
|
||||
string type_;
|
||||
|
|
@ -307,7 +307,7 @@ namespace diff{
|
|||
/* ==== Exposing scope and contents for iteration ====== */
|
||||
|
||||
using iterator = IterAdapter<ElmIter, const Record*>;
|
||||
using scopeIter = typename iter_stl::_SeqT<const Storage>::Range;
|
||||
using scopeIter = iter_stl::_SeqT<const Storage>::Range;
|
||||
using keyIter = TransformIter<scopeIter, string>;
|
||||
using valIter = TransformIter<scopeIter, Access>;
|
||||
|
||||
|
|
@ -595,10 +595,10 @@ namespace diff{
|
|||
* @see tree-diff-application.hpp
|
||||
*/
|
||||
template<typename VAL>
|
||||
inline typename Record<VAL>::Mutator&
|
||||
inline Record<VAL>::Mutator&
|
||||
mutateInPlace (Record<VAL>& record_to_mutate)
|
||||
{
|
||||
return reinterpret_cast<typename Record<VAL>::Mutator &> (record_to_mutate);
|
||||
return reinterpret_cast<Record<VAL>::Mutator &> (record_to_mutate);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -713,8 +713,8 @@ namespace diff{
|
|||
struct RecordSetup<string>
|
||||
{
|
||||
using Storage = std::vector<string>;
|
||||
using ElmIter = typename Storage::const_iterator;
|
||||
using Access = string; ///< data access by value copy
|
||||
using ElmIter = Storage::const_iterator;
|
||||
using Access = string; ///< data access by value copy
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -195,8 +195,8 @@ namespace diff{
|
|||
|
||||
|
||||
public:
|
||||
using iterator = typename iter_stl::_SeqT<VecG>::Range;
|
||||
using const_iterator = typename iter_stl::_SeqT<const VecG>::Range;
|
||||
using iterator = iter_stl::_SeqT<VecG>::Range;
|
||||
using const_iterator = iter_stl::_SeqT<const VecG>::Range;
|
||||
|
||||
const_iterator begin() const { return eachElm(content_); }
|
||||
const_iterator end() const { return const_iterator(); }
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ namespace diff{
|
|||
void
|
||||
initDiffApplication()
|
||||
{
|
||||
using Target = typename TreeDiffTraits<TAR>::Ret;
|
||||
using Target = TreeDiffTraits<TAR>::Ret;
|
||||
|
||||
Target target = mutatorBinding (subject_);
|
||||
buildMutator(target)->init();
|
||||
|
|
|
|||
|
|
@ -200,10 +200,10 @@ namespace diff{
|
|||
* the return value in local scope as long as necessary
|
||||
*/
|
||||
template<class TAR>
|
||||
typename TreeDiffTraits<TAR>::Ret
|
||||
TreeDiffTraits<TAR>::Ret
|
||||
mutatorBinding (TAR& subject)
|
||||
{
|
||||
using Wrapper = typename TreeDiffTraits<TAR>::Ret;
|
||||
using Wrapper = TreeDiffTraits<TAR>::Ret;
|
||||
return Wrapper(subject);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -236,9 +236,9 @@ namespace diff{
|
|||
class ChangeOperation
|
||||
: public AttributeBindingBase<PAR>
|
||||
{
|
||||
using CloArgs = typename lib::meta::_Fun<CLO>::Args;
|
||||
using ValueType = typename lib::meta::Pick<CloArgs, 0>::Type;
|
||||
using ID = idi::EntryID<ValueType>;
|
||||
using CloArgs = lib::meta::_Fun<CLO>::Args;
|
||||
using ValueType = lib::meta::Pick<CloArgs, 0>::Type;
|
||||
using ID = idi::EntryID<ValueType>;
|
||||
|
||||
|
||||
CLO setter_;
|
||||
|
|
|
|||
|
|
@ -121,8 +121,8 @@ namespace diff{
|
|||
struct ContainerTraits<V, IF_is_vector<V> >
|
||||
{
|
||||
using Vec = _AsVector<V>;
|
||||
using Elm = typename Vec::value_type;
|
||||
using Itr = typename Vec::iterator;
|
||||
using Elm = Vec::value_type;
|
||||
using Itr = Vec::iterator;
|
||||
|
||||
static Itr
|
||||
recentElmRawIter (Vec& vec)
|
||||
|
|
@ -141,8 +141,8 @@ namespace diff{
|
|||
struct ContainerTraits<M, IF_is_map<M> >
|
||||
{
|
||||
using Map = _AsMap<M>;
|
||||
using Key = typename Map::key_type;
|
||||
using Val = typename Map::mapped_type;
|
||||
using Key = Map::key_type;
|
||||
using Val = Map::mapped_type;
|
||||
using Elm = std::pair<const Key, Val>;
|
||||
|
||||
/** heuristic for `std::map`: lookup via reverse iterator.
|
||||
|
|
@ -188,12 +188,12 @@ namespace diff{
|
|||
struct CollectionBinding
|
||||
: util::MoveOnly
|
||||
{
|
||||
using Coll = typename Strip<COLL>::TypeReferred;
|
||||
using Elm = typename Coll::value_type;
|
||||
using Coll = Strip<COLL>::TypeReferred;
|
||||
using Elm = Coll::value_type;
|
||||
using Trait = ContainerTraits<Coll>;
|
||||
|
||||
using iterator = typename lib::iter_stl::_SeqT<Coll>::Range;
|
||||
using const_iterator = typename lib::iter_stl::_SeqT<const Coll>::Range;
|
||||
using iterator = lib::iter_stl::_SeqT<Coll>::Range;
|
||||
using const_iterator = lib::iter_stl::_SeqT<const Coll>::Range;
|
||||
|
||||
|
||||
ASSERT_VALID_SIGNATURE (MAT, bool(GenNode const& spec, Elm const& elm))
|
||||
|
|
@ -306,7 +306,7 @@ namespace diff{
|
|||
class ChildCollectionMutator
|
||||
: public PAR
|
||||
{
|
||||
using Iter = typename BIN::iterator;
|
||||
using Iter = BIN::iterator;
|
||||
|
||||
BIN binding_;
|
||||
Iter pos_;
|
||||
|
|
@ -582,7 +582,7 @@ namespace diff{
|
|||
inline auto
|
||||
createCollectionBindingBuilder (COLL& coll, MAT m, CTR c, SEL s, ASS a, MUT u)
|
||||
{
|
||||
using Coll = typename Strip<COLL>::TypeReferred;
|
||||
using Coll = Strip<COLL>::TypeReferred;
|
||||
|
||||
return CollectionBindingBuilder<Coll, MAT,CTR,SEL,ASS,MUT> {coll, m,c,s,a,u};
|
||||
}
|
||||
|
|
@ -738,7 +738,7 @@ namespace diff{
|
|||
inline auto
|
||||
collection (COLL& coll)
|
||||
{
|
||||
using Elm = typename COLL::value_type;
|
||||
using Elm = COLL::value_type;
|
||||
|
||||
return _DefaultBinding<Elm>::attachTo(coll);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ namespace lib {
|
|||
: public std::vector<P<ELM>>
|
||||
{
|
||||
using _Vec = std::vector<P<ELM>>;
|
||||
using Iter = typename _Vec::iterator;
|
||||
using CIter = typename _Vec::const_iterator;
|
||||
using Iter = _Vec::iterator;
|
||||
using CIter = _Vec::const_iterator;
|
||||
|
||||
public:
|
||||
~ElementTracker()
|
||||
|
|
@ -226,7 +226,7 @@ namespace lib {
|
|||
/** storage for the functor to link an AutoRegistered entity
|
||||
* to the corresponding registration service */
|
||||
template<typename TAR>
|
||||
typename AutoRegistered<TAR>::RegistryLink AutoRegistered<TAR>::getRegistry;
|
||||
AutoRegistered<TAR>::RegistryLink AutoRegistered<TAR>::getRegistry;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,19 +39,20 @@
|
|||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
using CStr = const char*;
|
||||
|
||||
|
||||
#define LERR_(_NAME_) lumiera::error::LUMIERA_ERROR_##_NAME_
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
using std::string;
|
||||
using CStr = const char*;
|
||||
|
||||
namespace error {
|
||||
/** error-ID for unspecified exceptions */
|
||||
LUMIERA_ERROR_DECLARE(EXCEPTION);
|
||||
}
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface and Base definition for all Lumiera Exceptions.
|
||||
|
|
@ -266,13 +267,13 @@ namespace lumiera {
|
|||
#define ERROR_LOG_AND_IGNORE(_FLAG_,_OP_DESCR_) \
|
||||
catch (std::exception& problem) \
|
||||
{ \
|
||||
const char* errID = lumiera_error(); \
|
||||
CStr errID = lumiera_error(); \
|
||||
WARN (_FLAG_, "%s failed: %s", _OP_DESCR_, problem.what()); \
|
||||
TRACE (debugging, "Error flag was: %s", errID);\
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
const char* errID = lumiera_error(); \
|
||||
CStr errID = lumiera_error(); \
|
||||
ERROR (_FLAG_, "%s failed with unknown exception; " \
|
||||
"error flag is: %s" \
|
||||
, _OP_DESCR_, errID?errID:"??"); \
|
||||
|
|
@ -281,14 +282,14 @@ namespace lumiera {
|
|||
#define ERROR_LOG_AND_RETHROW(_FLAG_,_OP_DESCR_) \
|
||||
catch (std::exception& problem) \
|
||||
{ \
|
||||
const char* errID = lumiera_error(); \
|
||||
CStr errID = lumiera_error(); \
|
||||
WARN (_FLAG_, "%s failed: %s", _OP_DESCR_, problem.what()); \
|
||||
TRACE (debugging, "Error flag was: %s", errID); \
|
||||
throw; \
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
const char* errID = lumiera_error(); \
|
||||
CStr errID = lumiera_error(); \
|
||||
ERROR (_FLAG_, "%s failed with unknown exception; " \
|
||||
"error flag is: %s" \
|
||||
, _OP_DESCR_, errID?errID:"??"); \
|
||||
|
|
@ -304,7 +305,7 @@ namespace lumiera {
|
|||
#define ON_EXCEPTION_RETURN(_VAL_,_OP_DESCR_) \
|
||||
catch (std::exception& problem) \
|
||||
{ \
|
||||
const char* errID = lumiera_error(); \
|
||||
CStr errID = lumiera_error(); \
|
||||
WARN (stage, "%s (Handler) failed: %s", \
|
||||
_OP_DESCR_, problem.what()); \
|
||||
TRACE (debugging, "Error flag was: %s", errID); \
|
||||
|
|
@ -312,7 +313,7 @@ namespace lumiera {
|
|||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
const char* errID = lumiera_error(); \
|
||||
CStr errID = lumiera_error(); \
|
||||
ERROR (stage, "(Handler) %s failed with " \
|
||||
"unknown exception; error flag is: %s" \
|
||||
, _OP_DESCR_, errID?errID:"??"); \
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ namespace util {
|
|||
inline std::string
|
||||
toString (TY const& val) noexcept
|
||||
{
|
||||
using PlainVal = typename lib::meta::Strip<TY>::TypeReferred;
|
||||
using PlainVal = lib::meta::Strip<TY>::TypeReferred;
|
||||
return StringConv<PlainVal>::invoke (val);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace util {
|
|||
/** in case the formatting of a (primitive) value fails,
|
||||
* we try to supply an error indicator instead */
|
||||
void
|
||||
pushFailsafeReplacement (std::byte* formatter, const char* errorMsg =NULL)
|
||||
pushFailsafeReplacement (std::byte* formatter, CStr errorMsg =nullptr)
|
||||
try {
|
||||
string placeholder("<Error");
|
||||
if (errorMsg){
|
||||
|
|
|
|||
|
|
@ -182,11 +182,11 @@ namespace util {
|
|||
friend std::ostream&
|
||||
operator<< (std::ostream& os, _Fmt const&);
|
||||
|
||||
friend bool operator== (_Fmt const&, _Fmt const&);
|
||||
friend bool operator== (_Fmt const&, string const&);
|
||||
friend bool operator== (_Fmt const&, const char * const);
|
||||
friend bool operator== (string const& , _Fmt const&);
|
||||
friend bool operator== (const char * const, _Fmt const&);
|
||||
friend bool operator== (_Fmt const&, _Fmt const&);
|
||||
friend bool operator== (_Fmt const&, string const&);
|
||||
friend bool operator== (_Fmt const&, CStr const );
|
||||
friend bool operator== (string const&, _Fmt const&);
|
||||
friend bool operator== (CStr const, _Fmt const&);
|
||||
|
||||
template<typename X>
|
||||
friend bool operator != (_Fmt const& fmt, X const& x) { return not (fmt == x); }
|
||||
|
|
@ -299,7 +299,7 @@ namespace util {
|
|||
inline void
|
||||
_clear_errorflag()
|
||||
{
|
||||
const char* errID = lumiera_error();
|
||||
CStr errID = lumiera_error();
|
||||
TRACE_IF (errID, progress, "Lumiera errorstate '%s' cleared.", errID);
|
||||
}
|
||||
|
||||
|
|
@ -318,7 +318,7 @@ namespace util {
|
|||
inline string
|
||||
_log_unknown_exception()
|
||||
{
|
||||
const char* errID = lumiera_error();
|
||||
CStr errID = lumiera_error();
|
||||
if (errID)
|
||||
ERROR (progress, "Unknown error while invoking custom string conversion. Lumiera error flag = %s", errID);
|
||||
else
|
||||
|
|
@ -368,10 +368,10 @@ namespace util {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct _Fmt::Converter<const char *>
|
||||
struct _Fmt::Converter<CStr>
|
||||
{
|
||||
static void
|
||||
dump (const char* cString, Implementation& impl)
|
||||
dump (CStr cString, Implementation& impl)
|
||||
{
|
||||
format (cString? cString : BOTTOM_INDICATOR, impl);
|
||||
}
|
||||
|
|
@ -473,7 +473,7 @@ namespace util {
|
|||
}
|
||||
|
||||
inline bool
|
||||
operator== (_Fmt const& fmt, const char * const cString)
|
||||
operator== (_Fmt const& fmt, CStr const cString)
|
||||
{
|
||||
return string(fmt) == string(cString);
|
||||
}
|
||||
|
|
@ -485,7 +485,7 @@ namespace util {
|
|||
}
|
||||
|
||||
inline bool
|
||||
operator== (const char * const cString, _Fmt const& fmt)
|
||||
operator== (CStr const cString, _Fmt const& fmt)
|
||||
{
|
||||
return fmt == cString;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ namespace util {
|
|||
inline auto
|
||||
stringify (IT&& src)
|
||||
{
|
||||
using Val = typename lib::meta::ValueTypeBinding<IT>::value_type;
|
||||
using Val = lib::meta::ValueTypeBinding<IT>::value_type;
|
||||
|
||||
return lib::transformIterator(forward<IT>(src), util::toString<Val>);
|
||||
}
|
||||
|
|
@ -144,7 +144,7 @@ namespace util {
|
|||
template<class CON, typename TOGGLE = void>
|
||||
struct _RangeIter
|
||||
{
|
||||
using StlIter = typename CON::const_iterator;
|
||||
using StlIter = CON::const_iterator;
|
||||
|
||||
lib::RangeIter<StlIter> iter;
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ namespace util {
|
|||
inline string
|
||||
join (COLL&& coll, string const& delim =", ")
|
||||
{
|
||||
using Coll = typename lib::meta::Strip<COLL>::TypePlain;
|
||||
using Coll = lib::meta::Strip<COLL>::TypePlain;
|
||||
_RangeIter<Coll> range(std::forward<COLL>(coll)); // copies when CON is reference
|
||||
|
||||
auto strings = stringify (std::move (range.iter));
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
** @deprecated 10/2024 seems very likely that similar functionality moves down
|
||||
** into the render-engine implementation and will no longer be considered
|
||||
** a constituent of the public interface.
|
||||
** @todo 6/2025 basically everything here is unused or will likely be done
|
||||
** in a different way — expect this and rendergraph.cpp to be obsolete
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -31,7 +33,8 @@
|
|||
#define LUMIERA_FRAMEID_H
|
||||
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include "lib/integral.hpp"
|
||||
#include <compare>
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
|
|
@ -73,15 +76,14 @@ namespace lumiera {
|
|||
* later on define what is actually needed; this header should then
|
||||
* be replaced by a combined C/C++ header
|
||||
*/
|
||||
class FrameID : boost::totally_ordered<FrameID> ////////////TODO it seems we don't need total ordering, only comparison. Clarify this!
|
||||
class FrameID
|
||||
{
|
||||
long dummy;
|
||||
public:
|
||||
FrameID(long dum=0) : dummy(dum) {}
|
||||
operator long () { return dummy; }
|
||||
|
||||
bool operator< (const FrameID& other) const { return dummy < other.dummy; }
|
||||
bool operator== (const FrameID& other) const { return dummy == other.dummy; }
|
||||
auto operator<=> (FrameID const&) const =default;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ namespace lib {
|
|||
|
||||
/** access type to reside in the given slot of the _complete chain_ */
|
||||
template<size_t slot>
|
||||
using Elm_t = typename PickType<slot>::type;
|
||||
using Elm_t = PickType<slot>::type;
|
||||
|
||||
|
||||
/** access data elements within _complete chain_ by index pos */
|
||||
|
|
@ -272,10 +272,10 @@ namespace lib {
|
|||
}
|
||||
|
||||
template<typename...XVALS>
|
||||
using ChainExtent = typename ChainType::template Chain<XVALS...>;
|
||||
using ChainExtent = ChainType::template Chain<XVALS...>;
|
||||
|
||||
template<size_t slot>
|
||||
using Accessor = typename ChainType::template Accessor<_Self::size()+slot>;
|
||||
using Accessor = ChainType::template Accessor<_Self::size()+slot>;
|
||||
|
||||
template<typename X>
|
||||
using AccessorFor = Accessor<meta::indexOfType<X,VALS...>()>;
|
||||
|
|
@ -310,7 +310,7 @@ namespace lib {
|
|||
using _FrontBlock = HeteroData<meta::Node<StorageFrame<0, DATA...>, meta::Nil>>;
|
||||
|
||||
public:
|
||||
using NewFrame = typename _FrontBlock::Frame;
|
||||
using NewFrame = _FrontBlock::Frame;
|
||||
using ChainType = _FrontBlock;
|
||||
using _FrontBlock::_FrontBlock;
|
||||
|
||||
|
|
@ -434,7 +434,7 @@ namespace std { // Specialisation to support C++ »Tuple Protocol« and structur
|
|||
template<size_t I, typename...DATA>
|
||||
struct tuple_element<I, lib::HeteroData<DATA...> >
|
||||
{
|
||||
using type = typename lib::HeteroData<DATA...>::template Elm_t<I>;
|
||||
using type = lib::HeteroData<DATA...>::template Elm_t<I>;
|
||||
};
|
||||
template<size_t I>
|
||||
struct tuple_element<I, lib::HeteroData<lib::meta::Nil> >
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <compare>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
|
@ -131,7 +131,6 @@ namespace idi {
|
|||
* for building a combined hash and symbolic ID.
|
||||
*/
|
||||
class BareEntryID
|
||||
: public boost::equality_comparable<BareEntryID>
|
||||
{
|
||||
|
||||
string symbol_;
|
||||
|
|
@ -217,7 +216,6 @@ namespace idi {
|
|||
template<class TY>
|
||||
struct EntryID
|
||||
: BareEntryID
|
||||
, boost::totally_ordered< EntryID<TY> >
|
||||
{
|
||||
|
||||
/** case-1: auto generated symbolic ID */
|
||||
|
|
@ -234,7 +232,7 @@ namespace idi {
|
|||
: BareEntryID (util::sanitise(symbolID), getTypeHash<TY>())
|
||||
{ }
|
||||
explicit
|
||||
EntryID (const char* symbolID)
|
||||
EntryID (CStr symbolID)
|
||||
: BareEntryID (util::sanitise(symbolID), getTypeHash<TY>())
|
||||
{ }
|
||||
|
||||
|
|
@ -272,15 +270,17 @@ namespace idi {
|
|||
explicit
|
||||
operator string() const;
|
||||
|
||||
friend bool operator< (EntryID const& i1, EntryID const& i2) { return i1.getSym() < i2.getSym(); }
|
||||
friend auto operator<=> (EntryID const& i1, EntryID const& i2) { return i1.getSym() <=> i2.getSym(); }
|
||||
};
|
||||
|
||||
|
||||
inline bool
|
||||
operator== (BareEntryID const& i1, BareEntryID const& i2)
|
||||
{
|
||||
return i1.getHash() == i2.getHash();
|
||||
}
|
||||
// Note: since we allow comparison only between EntryIDs of same type
|
||||
// and also feed-down the symbol into the hash value, both equality
|
||||
// and (total) ordering mesh up perfectly.
|
||||
|
||||
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ namespace idi {
|
|||
RandID (string const& symbolID)
|
||||
: BareEntryID{util::sanitise (symbolID)}
|
||||
{ }
|
||||
RandID (const char* symbolID)
|
||||
RandID (CStr symbolID)
|
||||
: BareEntryID{util::sanitise (symbolID)}
|
||||
{ }
|
||||
RandID (Symbol const& internalSymbol)
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ namespace lib {
|
|||
|
||||
using ResVal = decltype(data_->operator[](0));
|
||||
|
||||
using value_type = typename meta::RefTraits<ResVal>::Value;
|
||||
using reference = typename meta::RefTraits<ResVal>::Reference;
|
||||
using value_type = meta::RefTraits<ResVal>::Value;
|
||||
using reference = meta::RefTraits<ResVal>::Reference;
|
||||
|
||||
bool
|
||||
checkPoint() const
|
||||
|
|
@ -113,7 +113,7 @@ namespace lib {
|
|||
: public iter::IndexAccessCore<PTR>::IterWrapper
|
||||
{
|
||||
using _Cor = iter::IndexAccessCore<PTR>;
|
||||
using _Par = typename _Cor::IterWrapper;
|
||||
using _Par = _Cor::IterWrapper;
|
||||
|
||||
public:
|
||||
IndexIter() = default;
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ namespace lib {
|
|||
|
||||
public:
|
||||
/** this iterator adapter is meant to wrap an iterator yielding pointer values */
|
||||
using pointer = typename meta::ValueTypeBinding<IT>::value_type;
|
||||
using pointer = meta::ValueTypeBinding<IT>::value_type;
|
||||
static_assert(std::is_pointer_v<pointer>);
|
||||
|
||||
using value_type = typename std::remove_pointer_t<pointer>;
|
||||
using value_type = std::remove_pointer_t<pointer>;
|
||||
using reference = value_type&;
|
||||
|
||||
|
||||
|
|
@ -72,10 +72,10 @@ namespace lib {
|
|||
|
||||
// the purpose of the following typedefs is to support building a correct "const iterator"
|
||||
|
||||
using ValueTypeBase = typename std::remove_const_t<value_type>; // value_type without const
|
||||
using ValueTypeBase = std::remove_const_t<value_type>; // value_type without const
|
||||
|
||||
using WrappedIterType = typename IterType<IT>::template SimilarIter< ValueTypeBase* * >::Type;
|
||||
using WrappedConstIterType = typename IterType<IT>::template SimilarIter<const ValueTypeBase* * >::Type;
|
||||
using WrappedIterType = IterType<IT>::template SimilarIter< ValueTypeBase* * >::Type;
|
||||
using WrappedConstIterType = IterType<IT>::template SimilarIter<const ValueTypeBase* * >::Type;
|
||||
|
||||
using IterType = PtrDerefIter<WrappedIterType>;
|
||||
using ConstIterType = PtrDerefIter<WrappedConstIterType>;
|
||||
|
|
@ -220,7 +220,7 @@ namespace lib {
|
|||
template<class IT>
|
||||
class AddressExposingIter
|
||||
{
|
||||
using _Ptr = typename IT::pointer;
|
||||
using _Ptr = IT::pointer;
|
||||
|
||||
IT i_; ///< nested source iterator
|
||||
|
||||
|
|
@ -238,9 +238,9 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
using pointer = typename IT::pointer const*;
|
||||
using reference = typename IT::pointer const&;
|
||||
using value_type = typename IT::pointer const ;
|
||||
using pointer = IT::pointer const*;
|
||||
using reference = IT::pointer const&;
|
||||
using value_type = IT::pointer const ;
|
||||
|
||||
ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (AddressExposingIter);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ namespace iter_stl {
|
|||
class DistinctIter
|
||||
{
|
||||
public:
|
||||
using value_type = typename IT::value_type;
|
||||
using reference = typename IT::reference;
|
||||
using pointer = typename IT::pointer;
|
||||
using value_type = IT::value_type;
|
||||
using reference = IT::reference;
|
||||
using pointer = IT::pointer;
|
||||
|
||||
private:
|
||||
IT i_;
|
||||
|
|
@ -96,9 +96,9 @@ namespace iter_stl {
|
|||
template<typename DEF>
|
||||
struct WrappedStlIter : DEF
|
||||
{
|
||||
using Iter = typename DEF::Iter;
|
||||
using reference = typename DEF::reference;
|
||||
using pointer = typename DEF::pointer;
|
||||
using Iter = DEF::Iter;
|
||||
using reference = DEF::reference;
|
||||
using pointer = DEF::pointer;
|
||||
|
||||
|
||||
WrappedStlIter() : i_() { }
|
||||
|
|
@ -127,9 +127,9 @@ namespace iter_stl {
|
|||
struct Wrapped_Identity
|
||||
{
|
||||
using Iter = IT;
|
||||
using value_type = typename IT::value_type;
|
||||
using reference = typename IT::reference;
|
||||
using pointer = typename IT::pointer;
|
||||
using value_type = IT::value_type;
|
||||
using reference = IT::reference;
|
||||
using pointer = IT::pointer;
|
||||
|
||||
static Iter get (Iter& it) { return & (*it); }
|
||||
};
|
||||
|
|
@ -142,7 +142,7 @@ namespace iter_stl {
|
|||
struct Wrapped_PickKey
|
||||
{
|
||||
using Iter = IT;
|
||||
using value_type = typename IT::value_type::first_type;
|
||||
using value_type = IT::value_type::first_type;
|
||||
using reference = value_type &;
|
||||
using pointer = value_type *;
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ namespace iter_stl {
|
|||
struct Wrapped_PickVal
|
||||
{
|
||||
using Iter = IT;
|
||||
using value_type = typename IT::value_type::second_type;
|
||||
using value_type = IT::value_type::second_type;
|
||||
using reference = value_type &;
|
||||
using pointer = value_type *;
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ namespace iter_stl {
|
|||
struct Wrapped_PickConstVal
|
||||
{
|
||||
using Iter = IT;
|
||||
using value_type = const typename IT::value_type::second_type;
|
||||
using value_type = const IT::value_type::second_type;
|
||||
using reference = const value_type &;
|
||||
using pointer = const value_type *;
|
||||
|
||||
|
|
@ -185,17 +185,17 @@ namespace iter_stl {
|
|||
template<class MAP>
|
||||
struct _MapTypeSelector
|
||||
{
|
||||
using Key = typename MAP::value_type::first_type;
|
||||
using Val = typename MAP::value_type::second_type;
|
||||
using Itr = typename MAP::iterator;
|
||||
using Key = MAP::value_type::first_type;
|
||||
using Val = MAP::value_type::second_type;
|
||||
using Itr = MAP::iterator;
|
||||
};
|
||||
|
||||
template<class MAP>
|
||||
struct _MapTypeSelector<const MAP>
|
||||
{
|
||||
using Key = typename MAP::value_type::first_type;
|
||||
using Val = typename MAP::value_type::second_type const;
|
||||
using Itr = typename MAP::const_iterator;
|
||||
using Key = MAP::value_type::first_type;
|
||||
using Val = MAP::value_type::second_type const;
|
||||
using Itr = MAP::const_iterator;
|
||||
};
|
||||
|
||||
/** helper to access the parts of the pair values correctly...*/
|
||||
|
|
@ -219,13 +219,13 @@ namespace iter_stl {
|
|||
template<class MAP>
|
||||
struct _MapT
|
||||
{
|
||||
using KeyType = typename _MapTypeSelector<MAP>::Key;
|
||||
using ValType = typename _MapTypeSelector<MAP>::Val;
|
||||
using EntryIter = typename _MapTypeSelector<MAP>::Itr;
|
||||
using KeyType = _MapTypeSelector<MAP>::Key;
|
||||
using ValType = _MapTypeSelector<MAP>::Val;
|
||||
using EntryIter = _MapTypeSelector<MAP>::Itr;
|
||||
|
||||
using DetectConst = typename EntryIter::reference;
|
||||
using PickKeyIter = typename _MapSubSelector<EntryIter,DetectConst>::PickKey;
|
||||
using PickValIter = typename _MapSubSelector<EntryIter,DetectConst>::PickVal;
|
||||
using DetectConst = EntryIter::reference;
|
||||
using PickKeyIter = _MapSubSelector<EntryIter,DetectConst>::PickKey;
|
||||
using PickValIter = _MapSubSelector<EntryIter,DetectConst>::PickVal;
|
||||
|
||||
using KeyIter = RangeIter<PickKeyIter>;
|
||||
using ValIter = RangeIter<PickValIter>;
|
||||
|
|
@ -239,12 +239,12 @@ namespace iter_stl {
|
|||
{
|
||||
using EntryIter = IT;
|
||||
|
||||
using KeyType = typename EntryIter::value_type::first_type;
|
||||
using ValType = typename EntryIter::value_type::second_type;
|
||||
using KeyType = EntryIter::value_type::first_type;
|
||||
using ValType = EntryIter::value_type::second_type;
|
||||
|
||||
using DetectConst = typename EntryIter::reference;
|
||||
using PickKeyIter = typename _MapSubSelector<EntryIter,DetectConst>::PickKey;
|
||||
using PickValIter = typename _MapSubSelector<EntryIter,DetectConst>::PickVal;
|
||||
using DetectConst = EntryIter::reference;
|
||||
using PickKeyIter = _MapSubSelector<EntryIter,DetectConst>::PickKey;
|
||||
using PickValIter = _MapSubSelector<EntryIter,DetectConst>::PickVal;
|
||||
|
||||
using KeyIter = RangeIter<PickKeyIter>;
|
||||
using ValIter = RangeIter<PickValIter>;
|
||||
|
|
@ -257,7 +257,7 @@ namespace iter_stl {
|
|||
template<class SEQ>
|
||||
struct _SeqT
|
||||
{
|
||||
using Iter = typename SEQ::iterator;
|
||||
using Iter = SEQ::iterator;
|
||||
using Range = RangeIter<Iter>;
|
||||
using DistinctVals = DistinctIter<Range>;
|
||||
using Addrs = AddressExposingIter<Range>;
|
||||
|
|
@ -266,7 +266,7 @@ namespace iter_stl {
|
|||
template<class SEQ>
|
||||
struct _SeqT<const SEQ>
|
||||
{
|
||||
using Iter = typename SEQ::const_iterator;
|
||||
using Iter = SEQ::const_iterator;
|
||||
using Range = RangeIter<Iter>;
|
||||
using DistinctVals = DistinctIter<Range>;
|
||||
using Addrs = AddressExposingIter<Range>;
|
||||
|
|
@ -281,10 +281,10 @@ namespace iter_stl {
|
|||
* to yield each Element from a STL container
|
||||
*/
|
||||
template<class CON>
|
||||
inline typename _SeqT<CON>::Range
|
||||
inline _SeqT<CON>::Range
|
||||
eachElm (CON& coll)
|
||||
{
|
||||
using Range = typename _SeqT<CON>::Range;
|
||||
using Range = _SeqT<CON>::Range;
|
||||
return Range (coll.begin(), coll.end());
|
||||
}
|
||||
|
||||
|
|
@ -293,10 +293,10 @@ namespace iter_stl {
|
|||
* exposing the address of each Element within a STL
|
||||
*/
|
||||
template<class CON>
|
||||
inline typename _SeqT<CON>::Addrs
|
||||
inline _SeqT<CON>::Addrs
|
||||
eachAddress (CON& coll)
|
||||
{
|
||||
using Addresses = typename _SeqT<CON>::Addrs;
|
||||
using Addresses = _SeqT<CON>::Addrs;
|
||||
return Addresses (eachElm (coll));
|
||||
}
|
||||
|
||||
|
|
@ -305,11 +305,11 @@ namespace iter_stl {
|
|||
* each key of a map/multimap
|
||||
*/
|
||||
template<class MAP>
|
||||
inline typename _MapT<MAP>::KeyIter
|
||||
inline _MapT<MAP>::KeyIter
|
||||
eachKey (MAP& map)
|
||||
{
|
||||
using Range = typename _MapT<MAP>::KeyIter;
|
||||
using PickKey = typename _MapT<MAP>::PickKeyIter;
|
||||
using Range = _MapT<MAP>::KeyIter;
|
||||
using PickKey = _MapT<MAP>::PickKeyIter;
|
||||
|
||||
return Range (PickKey (map.begin()), PickKey (map.end()));
|
||||
}
|
||||
|
|
@ -319,11 +319,11 @@ namespace iter_stl {
|
|||
* from a given range of (key,value) pairs
|
||||
*/
|
||||
template<class IT>
|
||||
inline typename _MapIterT<IT>::KeyIter
|
||||
inline _MapIterT<IT>::KeyIter
|
||||
eachKey (IT const& begin, IT const& end)
|
||||
{
|
||||
using Range = typename _MapIterT<IT>::KeyIter;
|
||||
using PickKey = typename _MapIterT<IT>::PickKeyIter;
|
||||
using Range = _MapIterT<IT>::KeyIter;
|
||||
using PickKey = _MapIterT<IT>::PickKeyIter;
|
||||
|
||||
return Range (PickKey (begin), PickKey (end));
|
||||
}
|
||||
|
|
@ -333,11 +333,11 @@ namespace iter_stl {
|
|||
* each value within a map/multimap
|
||||
*/
|
||||
template<class MAP>
|
||||
inline typename _MapT<MAP>::ValIter
|
||||
inline _MapT<MAP>::ValIter
|
||||
eachVal (MAP& map)
|
||||
{
|
||||
using Range = typename _MapT<MAP>::ValIter;
|
||||
using PickVal = typename _MapT<MAP>::PickValIter;
|
||||
using Range = _MapT<MAP>::ValIter;
|
||||
using PickVal = _MapT<MAP>::PickValIter;
|
||||
|
||||
return Range (PickVal (map.begin()), PickVal (map.end()));
|
||||
}
|
||||
|
|
@ -347,11 +347,11 @@ namespace iter_stl {
|
|||
* from a given range of (key,value) pairs
|
||||
*/
|
||||
template<class IT>
|
||||
inline typename _MapIterT<IT>::ValIter
|
||||
inline _MapIterT<IT>::ValIter
|
||||
eachVal (IT const& begin, IT const& end)
|
||||
{
|
||||
using Range = typename _MapIterT<IT>::ValIter;
|
||||
using PickVal = typename _MapIterT<IT>::PickValIter;
|
||||
using Range = _MapIterT<IT>::ValIter;
|
||||
using PickVal = _MapIterT<IT>::PickValIter;
|
||||
|
||||
return Range (PickVal (begin), PickVal (end));
|
||||
}
|
||||
|
|
@ -361,11 +361,11 @@ namespace iter_stl {
|
|||
* any repetitions in the given sequence.
|
||||
*/
|
||||
template<class SEQ>
|
||||
inline typename _SeqT<SEQ>::DistinctVals
|
||||
inline _SeqT<SEQ>::DistinctVals
|
||||
eachDistinct (SEQ& seq)
|
||||
{
|
||||
using Range = typename _SeqT<SEQ>::Range;
|
||||
using DistinctValues = typename _SeqT<SEQ>::DistinctVals;
|
||||
using Range = _SeqT<SEQ>::Range;
|
||||
using DistinctValues = _SeqT<SEQ>::DistinctVals;
|
||||
|
||||
return DistinctValues (Range (seq.begin(), seq.end()));
|
||||
}
|
||||
|
|
@ -376,7 +376,7 @@ namespace iter_stl {
|
|||
* @warning full scan of all keys, dropping repetitions
|
||||
*/
|
||||
template<class MAP>
|
||||
inline typename _MapT<MAP>::DistinctKeys
|
||||
inline _MapT<MAP>::DistinctKeys
|
||||
eachDistinctKey (MAP& map)
|
||||
{
|
||||
return typename _MapT<MAP>::DistinctKeys (eachKey (map));
|
||||
|
|
@ -388,12 +388,12 @@ namespace iter_stl {
|
|||
* @warning full scan of all keys, dropping repetitions
|
||||
*/
|
||||
template<class MMAP, typename KEY>
|
||||
inline typename _MapT<MMAP>::ValIter
|
||||
inline _MapT<MMAP>::ValIter
|
||||
eachValForKey (MMAP& multimap, KEY key)
|
||||
{
|
||||
using Pos = typename _MapT<MMAP>::EntryIter;
|
||||
using Range = typename _MapT<MMAP>::ValIter;
|
||||
using PickVal = typename _MapT<MMAP>::PickValIter;
|
||||
using Pos = _MapT<MMAP>::EntryIter;
|
||||
using Range = _MapT<MMAP>::ValIter;
|
||||
using PickVal = _MapT<MMAP>::PickValIter;
|
||||
|
||||
std::pair<Pos,Pos> valRange = multimap.equal_range (key);
|
||||
|
||||
|
|
|
|||
|
|
@ -212,9 +212,9 @@ namespace lib {
|
|||
using _ValTrait = meta::ValueTypeBinding<std::remove_pointer_t<POS>>;
|
||||
|
||||
public:
|
||||
using value_type = typename _ValTrait::value_type;
|
||||
using reference = typename _ValTrait::reference;
|
||||
using pointer = typename _ValTrait::pointer;
|
||||
using value_type = _ValTrait::value_type;
|
||||
using reference = _ValTrait::reference;
|
||||
using pointer = _ValTrait::pointer;
|
||||
|
||||
|
||||
IterAdapter (CON src, POS const& startpos)
|
||||
|
|
@ -302,7 +302,7 @@ namespace lib {
|
|||
|
||||
|
||||
protected:
|
||||
using ConRef = typename meta::RefTraits<CON>::Reference;
|
||||
using ConRef = meta::RefTraits<CON>::Reference;
|
||||
|
||||
/** allow derived classes to access backing container */
|
||||
ConRef source() { return source_; }
|
||||
|
|
@ -376,9 +376,9 @@ namespace lib {
|
|||
ST core_;
|
||||
|
||||
public:
|
||||
using value_type = typename meta::RefTraits<T>::Value;
|
||||
using reference = typename meta::RefTraits<T>::Reference;
|
||||
using pointer = typename meta::RefTraits<T>::Pointer;
|
||||
using value_type = meta::RefTraits<T>::Value;
|
||||
using reference = meta::RefTraits<T>::Reference;
|
||||
using pointer = meta::RefTraits<T>::Pointer;
|
||||
|
||||
IterStateWrapper (ST&& initialState)
|
||||
: core_(std::forward<ST>(initialState))
|
||||
|
|
@ -519,7 +519,7 @@ namespace lib {
|
|||
return bool(srcIter());
|
||||
}
|
||||
|
||||
typename IT::reference
|
||||
IT::reference
|
||||
yield() const
|
||||
{
|
||||
return *srcIter();
|
||||
|
|
@ -614,7 +614,7 @@ namespace lib {
|
|||
class ContainerCore
|
||||
: public CON
|
||||
{
|
||||
using Iter = typename CON::iterator;
|
||||
using Iter = CON::iterator;
|
||||
|
||||
Iter p_;
|
||||
|
||||
|
|
@ -694,9 +694,9 @@ namespace lib {
|
|||
|
||||
public:
|
||||
using YieldRes = iter::CoreYield<COR>;
|
||||
using value_type = typename meta::RefTraits<YieldRes>::Value;
|
||||
using reference = typename meta::RefTraits<YieldRes>::Reference;
|
||||
using pointer = typename meta::RefTraits<YieldRes>::Pointer;
|
||||
using value_type = meta::RefTraits<YieldRes>::Value;
|
||||
using reference = meta::RefTraits<YieldRes>::Reference;
|
||||
using pointer = meta::RefTraits<YieldRes>::Pointer;
|
||||
|
||||
|
||||
/** by default, pass anything down for initialisation of the core.
|
||||
|
|
@ -803,11 +803,11 @@ namespace lib {
|
|||
using _ValTrait = meta::ValueTypeBinding<meta::remove_pointer_t<IT>>;
|
||||
|
||||
public:
|
||||
using pointer = typename _ValTrait::pointer;
|
||||
using reference = typename _ValTrait::reference;
|
||||
using pointer = _ValTrait::pointer;
|
||||
using reference = _ValTrait::reference;
|
||||
|
||||
/// @note special twist, since a STL const_iterator would yield a non-const `value_type`
|
||||
using value_type = typename std::remove_reference<reference>::type;
|
||||
using value_type = std::remove_reference<reference>::type;
|
||||
|
||||
|
||||
RangeIter (IT const& start, IT const& end)
|
||||
|
|
@ -1052,7 +1052,7 @@ namespace lib {
|
|||
template<class T2>
|
||||
struct SimilarIter ///< rebind to rewritten Iterator wrapped into RangeIter
|
||||
{
|
||||
using WrappedIter = typename IterType<IT>::template SimilarIter<T2>::Type;
|
||||
using WrappedIter = IterType<IT>::template SimilarIter<T2>::Type;
|
||||
using Type = RangeIter<WrappedIter>;
|
||||
};
|
||||
};
|
||||
|
|
@ -1067,9 +1067,9 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
using value_type = const typename IT::value_type;
|
||||
using pointer = const typename IT::pointer ;
|
||||
using reference = const typename IT::reference ;
|
||||
using value_type = const IT::value_type;
|
||||
using pointer = const IT::pointer ;
|
||||
using reference = const IT::reference ;
|
||||
|
||||
ConstIter (IT srcIter)
|
||||
: i_(srcIter)
|
||||
|
|
|
|||
|
|
@ -150,11 +150,11 @@ namespace iter {
|
|||
: public _IterChainSetup<SRC>::Pipeline
|
||||
{
|
||||
using _Trait = _IterChainSetup<SRC>;
|
||||
using _Base = typename _Trait::Pipeline;
|
||||
using _Base = _Trait::Pipeline;
|
||||
|
||||
using Value = typename _Base::value_type;
|
||||
using Filter = typename _Trait::Filter;
|
||||
using Step = typename _Trait::StepFunctor;
|
||||
using Value = _Base::value_type;
|
||||
using Filter = _Trait::Filter;
|
||||
using Step = _Trait::StepFunctor;
|
||||
|
||||
/** Storage for a sequence of filter configuration functors */
|
||||
std::vector<Step> stepChain_;
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
using pointer = typename meta::ValueTypeBinding<IT>::pointer;
|
||||
using reference = typename meta::ValueTypeBinding<IT>::reference;
|
||||
using value_type = typename std::remove_reference<reference>::type; ///< @note will be const for const iterators (while const_iterator::value_type isn't)
|
||||
using pointer = meta::ValueTypeBinding<IT>::pointer;
|
||||
using reference = meta::ValueTypeBinding<IT>::reference;
|
||||
using value_type = std::remove_reference<reference>::type; ///< @note will be const for const iterators (while const_iterator::value_type isn't)
|
||||
|
||||
|
||||
CursorGear()
|
||||
|
|
|
|||
|
|
@ -133,9 +133,9 @@ namespace lib {
|
|||
namespace iter_explorer { // basic iterator wrappers...
|
||||
|
||||
template<class CON>
|
||||
using iterator = typename meta::Strip<CON>::TypeReferred::iterator;
|
||||
using iterator = meta::Strip<CON>::TypeReferred::iterator;
|
||||
template<class CON>
|
||||
using const_iterator = typename meta::Strip<CON>::TypeReferred::const_iterator;
|
||||
using const_iterator = meta::Strip<CON>::TypeReferred::const_iterator;
|
||||
|
||||
/**
|
||||
* Adapt STL compliant container.
|
||||
|
|
@ -190,7 +190,7 @@ namespace lib {
|
|||
class IterSourceIter
|
||||
: public ISO::iterator
|
||||
{
|
||||
using Iterator = typename ISO::iterator;
|
||||
using Iterator = ISO::iterator;
|
||||
|
||||
public:
|
||||
IterSourceIter() =default;
|
||||
|
|
@ -273,8 +273,8 @@ namespace lib {
|
|||
template<class SRC>
|
||||
struct _DecoratorTraits<SRC, enable_if<is_StateCore<SRC>>>
|
||||
{
|
||||
using SrcRaw = typename lib::meta::Strip<SRC>::Type;
|
||||
using SrcVal = typename meta::RefTraits<iter::CoreYield<SrcRaw>>::Value;
|
||||
using SrcRaw = lib::meta::Strip<SRC>::Type;
|
||||
using SrcVal = meta::RefTraits<iter::CoreYield<SrcRaw>>::Value;
|
||||
using SrcIter = lib::IterableDecorator<lib::CheckedCore<SrcRaw>>;
|
||||
};
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ namespace lib {
|
|||
struct _DecoratorTraits<SRC, enable_if<shall_use_Lumiera_Iter<SRC>>>
|
||||
{
|
||||
using SrcIter = remove_reference_t<SRC>;
|
||||
using SrcVal = typename SrcIter::value_type;
|
||||
using SrcVal = SrcIter::value_type;
|
||||
};
|
||||
|
||||
template<class SRC>
|
||||
|
|
@ -291,14 +291,14 @@ namespace lib {
|
|||
static_assert (not std::is_rvalue_reference<SRC>::value,
|
||||
"container needs to exist elsewhere during the lifetime of the iteration");
|
||||
using SrcIter = iter_explorer::StlRange<SRC>;
|
||||
using SrcVal = typename SrcIter::value_type;
|
||||
using SrcVal = SrcIter::value_type;
|
||||
};
|
||||
|
||||
template<class ISO>
|
||||
struct _DecoratorTraits<ISO*, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
|
||||
{
|
||||
using SrcIter = iter_explorer::IterSourceIter<ISO>;
|
||||
using SrcVal = typename ISO::value_type;
|
||||
using SrcVal = ISO::value_type;
|
||||
};
|
||||
|
||||
template<class ISO>
|
||||
|
|
@ -324,7 +324,7 @@ namespace lib {
|
|||
template<class SRC, class RES>
|
||||
struct _ExpanderTraits
|
||||
{
|
||||
using ResIter = typename _DecoratorTraits<RES>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<RES>::SrcIter;
|
||||
using SrcYield = iter::Yield<SRC>;
|
||||
using ResYield = iter::Yield<ResIter>;
|
||||
using _CommonT = meta::CommonResultYield<SrcYield,ResYield>;
|
||||
|
|
@ -336,10 +336,10 @@ namespace lib {
|
|||
static_assert (is_const_v<SrcYield> == is_const_v<ResYield>,
|
||||
"source and expanded types differ in const-ness");
|
||||
|
||||
using YieldRes = typename _CommonT::ResType;
|
||||
using value_type = typename _CommonT::value_type;
|
||||
using reference = typename _CommonT::reference;
|
||||
using pointer = typename _CommonT::pointer;
|
||||
using YieldRes = _CommonT::ResType;
|
||||
using value_type = _CommonT::value_type;
|
||||
using reference = _CommonT::reference;
|
||||
using pointer = _CommonT::pointer;
|
||||
};
|
||||
|
||||
}//(End) IterExplorer traits
|
||||
|
|
@ -389,22 +389,22 @@ namespace lib {
|
|||
template<typename F, typename SEL =void>
|
||||
struct FunDetector
|
||||
{
|
||||
using Sig = typename _Fun<F>::Sig;
|
||||
using Sig = _Fun<F>::Sig;
|
||||
};
|
||||
|
||||
/** handle a generic lambda, accepting a reference to the `SRC` iterator */
|
||||
template<typename F>
|
||||
struct FunDetector<F, disable_if<_Fun<F>> >
|
||||
{
|
||||
using Arg = typename std::add_lvalue_reference<SRC>::type;
|
||||
using Arg = std::add_lvalue_reference<SRC>::type;
|
||||
using Ret = decltype(std::declval<F>() (std::declval<Arg>()));
|
||||
using Sig = Ret(Arg);
|
||||
};
|
||||
|
||||
|
||||
using Sig = typename FunDetector<FUN>::Sig;
|
||||
using Arg = typename _Fun<Sig>::Args::List::Head; // assuming function with a single argument
|
||||
using Res = typename _Fun<Sig>::Ret;
|
||||
using Sig = FunDetector<FUN>::Sig;
|
||||
using Arg = _Fun<Sig>::Args::List::Head; // assuming function with a single argument
|
||||
using Res = _Fun<Sig>::Ret;
|
||||
static_assert (meta::is_UnaryFun<Sig>());
|
||||
|
||||
|
||||
|
|
@ -442,7 +442,7 @@ namespace lib {
|
|||
, is_base_of<IterSource<typename IT::value_type>, remove_reference_t<Arg>>
|
||||
> >>
|
||||
{
|
||||
using Source = typename IT::Source;
|
||||
using Source = IT::Source;
|
||||
|
||||
static auto
|
||||
wrap (function<Sig> rawFun) ///< extract the (abstracted) IterSource
|
||||
|
|
@ -466,7 +466,7 @@ namespace lib {
|
|||
inline void
|
||||
static_assert_isPredicate()
|
||||
{
|
||||
using Res = typename _FunTraits<FUN,SRC>::Res;
|
||||
using Res = _FunTraits<FUN,SRC>::Res;
|
||||
static_assert(std::is_constructible<bool, Res>::value, "Functor must be a predicate");
|
||||
}
|
||||
|
||||
|
|
@ -477,8 +477,8 @@ namespace lib {
|
|||
template<class SRC, class FUN>
|
||||
struct _ReduceTraits
|
||||
{
|
||||
using Result = typename iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||
using ResVal = typename lib::meta::RefTraits<Result>::Value;
|
||||
using Result = iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||
using ResVal = lib::meta::RefTraits<Result>::Value;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -557,7 +557,7 @@ namespace lib {
|
|||
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
|
||||
|
||||
using _Trait = _ExpanderTraits<SRC,RES>;
|
||||
using ResIter = typename _Trait::ResIter;
|
||||
using ResIter = _Trait::ResIter;
|
||||
using RootExpandFunctor = function<RES(SRC&)>;
|
||||
using ChldExpandFunctor = function<RES(ResIter&)>;
|
||||
|
||||
|
|
@ -621,10 +621,10 @@ namespace lib {
|
|||
public: /* === Iteration control API for IterableDecorator === */
|
||||
|
||||
/** @note result type bindings based on a common type of source and expanded result */
|
||||
using YieldRes = typename _Trait::YieldRes;
|
||||
using value_type = typename _Trait::value_type;
|
||||
using reference = typename _Trait::reference;
|
||||
using pointer = typename _Trait::pointer;
|
||||
using YieldRes = _Trait::YieldRes;
|
||||
using value_type = _Trait::value_type;
|
||||
using reference = _Trait::reference;
|
||||
using pointer = _Trait::pointer;
|
||||
|
||||
|
||||
bool
|
||||
|
|
@ -791,9 +791,9 @@ namespace lib {
|
|||
TransformedItem treated_;
|
||||
|
||||
public:
|
||||
using value_type = typename meta::ValueTypeBinding<RES>::value_type;
|
||||
using reference = typename meta::ValueTypeBinding<RES>::reference;
|
||||
using pointer = typename meta::ValueTypeBinding<RES>::pointer;
|
||||
using value_type = meta::ValueTypeBinding<RES>::value_type;
|
||||
using reference = meta::ValueTypeBinding<RES>::reference;
|
||||
using pointer = meta::ValueTypeBinding<RES>::pointer;
|
||||
|
||||
|
||||
template<typename FUN>
|
||||
|
|
@ -896,7 +896,7 @@ namespace lib {
|
|||
|
||||
protected:
|
||||
using Group = std::array<RES, grp>;
|
||||
using Iter = typename Group::iterator;
|
||||
using Iter = Group::iterator;
|
||||
struct Buffer
|
||||
: lib::UninitialisedStorage<RES,grp>
|
||||
{
|
||||
|
|
@ -1028,7 +1028,7 @@ namespace lib {
|
|||
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
|
||||
|
||||
protected:
|
||||
using SrcValue = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using SrcValue = meta::ValueTypeBinding<SRC>::value_type;
|
||||
using Grouping = function<GRP(SRC&)>;
|
||||
using Aggregator = function<void(AGG&, SrcValue&)>;
|
||||
|
||||
|
|
@ -1038,9 +1038,9 @@ namespace lib {
|
|||
Aggregator aggregate_;
|
||||
|
||||
public:
|
||||
using value_type = typename meta::RefTraits<AGG>::Value;
|
||||
using reference = typename meta::RefTraits<AGG>::Reference;
|
||||
using pointer = typename meta::RefTraits<AGG>::Pointer;
|
||||
using value_type = meta::RefTraits<AGG>::Value;
|
||||
using reference = meta::RefTraits<AGG>::Reference;
|
||||
using pointer = meta::RefTraits<AGG>::Pointer;
|
||||
|
||||
GroupAggregator() =default;
|
||||
// inherited default copy operations
|
||||
|
|
@ -1152,7 +1152,7 @@ namespace lib {
|
|||
return bool(srcIter());
|
||||
}
|
||||
|
||||
typename SRC::reference
|
||||
SRC::reference
|
||||
yield() const
|
||||
{
|
||||
return *srcIter();
|
||||
|
|
@ -1446,7 +1446,7 @@ namespace lib {
|
|||
, public ChildExpandableSource<typename SRC::value_type>
|
||||
{
|
||||
using Parent = WrappedLumieraIter<SRC>;
|
||||
using Val = typename SRC::value_type; ///////////////////////////////////TICKET #1125 : get rid of Val
|
||||
using Val = SRC::value_type; ///////////////////////////////////TICKET #1125 : get rid of Val
|
||||
|
||||
~PackagedIterExplorerSource() { }
|
||||
public:
|
||||
|
|
@ -1583,9 +1583,9 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
using value_type = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using reference = typename meta::ValueTypeBinding<SRC>::reference;
|
||||
using pointer = typename meta::ValueTypeBinding<SRC>::pointer;
|
||||
using value_type = meta::ValueTypeBinding<SRC>::value_type;
|
||||
using reference = meta::ValueTypeBinding<SRC>::reference;
|
||||
using pointer = meta::ValueTypeBinding<SRC>::pointer;
|
||||
|
||||
using TAG_IterExplorer_Src = SRC; ///< @internal for \ref _PipelineDetector
|
||||
|
||||
|
|
@ -1640,10 +1640,10 @@ namespace lib {
|
|||
auto
|
||||
expand (FUN&& expandFunctor)
|
||||
{
|
||||
using ExpandedChildren = typename iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||
using ExpandedChildren = iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||
|
||||
using ResCore = iter_explorer::Expander<SRC, ExpandedChildren>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(expandFunctor)});
|
||||
}
|
||||
|
|
@ -1664,7 +1664,7 @@ namespace lib {
|
|||
expandAll()
|
||||
{
|
||||
using ResCore = iter_explorer::AutoExpander<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this)});
|
||||
}
|
||||
|
|
@ -1692,7 +1692,7 @@ namespace lib {
|
|||
expandOnIteration()
|
||||
{
|
||||
using ResCore = iter_explorer::ScheduledExpander<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this)});
|
||||
}
|
||||
|
|
@ -1712,10 +1712,10 @@ namespace lib {
|
|||
auto
|
||||
transform (FUN&& transformFunctor)
|
||||
{
|
||||
using Product = typename iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||
using Product = iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||
|
||||
using ResCore = iter_explorer::Transformer<SRC, Product>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(transformFunctor)});
|
||||
}
|
||||
|
|
@ -1733,9 +1733,9 @@ namespace lib {
|
|||
auto
|
||||
grouped()
|
||||
{
|
||||
using Value = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using Value = meta::ValueTypeBinding<SRC>::value_type;
|
||||
using ResCore = iter_explorer::Grouping<SRC, Value, grp>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this)});
|
||||
}
|
||||
|
|
@ -1756,14 +1756,14 @@ namespace lib {
|
|||
auto
|
||||
groupedBy (FGRP&& groupFun, FAGG&& aggFun)
|
||||
{
|
||||
using GroupVal = typename iter_explorer::_FunTraits<FGRP,SRC>::Res;
|
||||
using GroupVal = iter_explorer::_FunTraits<FGRP,SRC>::Res;
|
||||
|
||||
static_assert (meta::is_BinaryFun<FAGG>());
|
||||
using ArgType1 = typename _Fun<FAGG>::Args::List::Head;
|
||||
using Aggregate = typename meta::RefTraits<ArgType1>::Value;
|
||||
using ArgType1 = _Fun<FAGG>::Args::List::Head;
|
||||
using Aggregate = meta::RefTraits<ArgType1>::Value;
|
||||
|
||||
using ResCore = iter_explorer::GroupAggregator<SRC, Aggregate, GroupVal>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this)
|
||||
,forward<FGRP> (groupFun)
|
||||
|
|
@ -1775,7 +1775,7 @@ namespace lib {
|
|||
auto
|
||||
groupedBy (FGRP&& groupFun)
|
||||
{
|
||||
using Value = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using Value = meta::ValueTypeBinding<SRC>::value_type;
|
||||
return groupedBy (forward<FGRP> (groupFun)
|
||||
,[](Value& agg, Value const& val){ agg += val; }
|
||||
);
|
||||
|
|
@ -1792,7 +1792,7 @@ namespace lib {
|
|||
iter_explorer::static_assert_isPredicate<FUN,SRC>();
|
||||
|
||||
using ResCore = iter_explorer::StopTrigger<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(whileCond)});
|
||||
}
|
||||
|
|
@ -1808,8 +1808,8 @@ namespace lib {
|
|||
iter_explorer::static_assert_isPredicate<FUN,SRC>();
|
||||
|
||||
using ResCore = iter_explorer::StopTrigger<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ArgType = typename iter_explorer::_FunTraits<FUN,SRC>::Arg;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ArgType = iter_explorer::_FunTraits<FUN,SRC>::Arg;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore { move(*this)
|
||||
,[whileCond = forward<FUN>(untilCond)](ArgType val)
|
||||
|
|
@ -1833,7 +1833,7 @@ namespace lib {
|
|||
iter_explorer::static_assert_isPredicate<FUN,SRC>();
|
||||
|
||||
using ResCore = iter_explorer::Filter<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(filterPredicate)});
|
||||
}
|
||||
|
|
@ -1863,7 +1863,7 @@ namespace lib {
|
|||
iter_explorer::static_assert_isPredicate<FUN,SRC>();
|
||||
|
||||
using ResCore = iter_explorer::MutableFilter<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(filterPredicate)});
|
||||
}
|
||||
|
|
@ -1893,7 +1893,7 @@ namespace lib {
|
|||
processingLayer()
|
||||
{
|
||||
using ResCore = LAY<SRC>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(*this)});
|
||||
}
|
||||
|
|
@ -1904,7 +1904,7 @@ namespace lib {
|
|||
auto
|
||||
asPtr()
|
||||
{
|
||||
using Val = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using Val = meta::ValueTypeBinding<SRC>::value_type;
|
||||
static_assert (not std::is_pointer_v<Val>);
|
||||
return IterExplorer::transform ([](Val& ref){ return &ref; });
|
||||
}
|
||||
|
|
@ -1913,7 +1913,7 @@ namespace lib {
|
|||
auto
|
||||
derefPtr()
|
||||
{
|
||||
using Ptr = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using Ptr = meta::ValueTypeBinding<SRC>::value_type;
|
||||
return IterExplorer::transform ([](Ptr ptr){ return *ptr; });
|
||||
}
|
||||
|
||||
|
|
@ -1925,9 +1925,9 @@ namespace lib {
|
|||
auto
|
||||
deduplicate()
|
||||
{
|
||||
using Value = typename meta::ValueTypeBinding<SRC>::value_type;
|
||||
using Value = meta::ValueTypeBinding<SRC>::value_type;
|
||||
using ResCore = ContainerCore<SET<Value>>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||
SET<Value> buffer;
|
||||
for (auto& val : *this)
|
||||
buffer.emplace (val);
|
||||
|
|
@ -2106,7 +2106,7 @@ namespace lib {
|
|||
template<class COR> // used when actually a CheckedCore was attached
|
||||
struct _UnstripAdapter<COR, std::void_t<typename COR::TAG_CheckedCore_Raw> >
|
||||
{
|
||||
using RawIter = typename COR::TAG_CheckedCore_Raw;
|
||||
using RawIter = COR::TAG_CheckedCore_Raw;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -2123,8 +2123,8 @@ namespace lib {
|
|||
template<class SRC>
|
||||
struct _PipelineDetector<SRC, std::void_t<typename SRC::TAG_IterExplorer_Src> >
|
||||
{
|
||||
using _SrcIT = typename SRC::TAG_IterExplorer_Src;
|
||||
using RawIter = typename _UnstripAdapter<_SrcIT>::RawIter;
|
||||
using _SrcIT = SRC::TAG_IterExplorer_Src;
|
||||
using RawIter = _UnstripAdapter<_SrcIT>::RawIter;
|
||||
};
|
||||
}//(End)internal adapter logic
|
||||
|
||||
|
|
@ -2188,9 +2188,9 @@ namespace lib {
|
|||
inline auto
|
||||
explore (IT&& srcSeq)
|
||||
{
|
||||
using RawIter = typename _PipelineDetector<IT>::RawIter; // possibly strip an underlying IterExplorer
|
||||
using SrcIter = typename _DecoratorTraits<RawIter>::SrcIter; // then decide how to adapt the source / iterator
|
||||
using Base = typename _BaseDetector<SrcIter>::BaseAdapter; // detect if a BaseAdapter exists or must be added
|
||||
using RawIter = _PipelineDetector<IT>::RawIter; // possibly strip an underlying IterExplorer
|
||||
using SrcIter = _DecoratorTraits<RawIter>::SrcIter; // then decide how to adapt the source / iterator
|
||||
using Base = _BaseDetector<SrcIter>::BaseAdapter; // detect if a BaseAdapter exists or must be added
|
||||
|
||||
return IterExplorer<Base> (std::forward<IT> (srcSeq));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ namespace lib {
|
|||
|
||||
/** storage for the empty data-source constant */
|
||||
template<typename TY>
|
||||
typename IterSource<TY>::iterator IterSource<TY>::EMPTY_SOURCE = iterator();
|
||||
IterSource<TY>::iterator IterSource<TY>::EMPTY_SOURCE = iterator();
|
||||
|
||||
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ namespace lib {
|
|||
IT src_;
|
||||
|
||||
protected:
|
||||
using Pos = typename ISO::Pos;
|
||||
using Pos = ISO::Pos;
|
||||
|
||||
Pos ////////////////////////////////////////////////////TICKET #1125 : this API should use three control functions, similar to IterStateWrapper
|
||||
firstResult ()
|
||||
|
|
@ -276,55 +276,55 @@ namespace lib {
|
|||
template<class CON>
|
||||
struct _SeqT
|
||||
{
|
||||
using Val = typename CON::iterator::value_type;
|
||||
using Iter = typename IterSource<Val>::iterator;
|
||||
using Val = CON::iterator::value_type;
|
||||
using Iter = IterSource<Val>::iterator;
|
||||
};
|
||||
|
||||
template<class IT>
|
||||
struct _RangeT
|
||||
{
|
||||
using Val = typename IT::value_type;
|
||||
using Iter = typename IterSource<Val>::iterator;
|
||||
using Val = IT::value_type;
|
||||
using Iter = IterSource<Val>::iterator;
|
||||
};
|
||||
|
||||
template<class MAP>
|
||||
struct _MapT
|
||||
{
|
||||
using Key = typename MAP::key_type;
|
||||
using Val = typename MAP::value_type::second_type;
|
||||
using KeyIter = typename IterSource<Key>::iterator;
|
||||
using ValIter = typename IterSource<Val>::iterator;
|
||||
using Key = MAP::key_type;
|
||||
using Val = MAP::value_type::second_type;
|
||||
using KeyIter = IterSource<Key>::iterator;
|
||||
using ValIter = IterSource<Val>::iterator;
|
||||
};
|
||||
|
||||
|
||||
template<class IT>
|
||||
struct _IterT
|
||||
{
|
||||
using Src = typename std::remove_reference<IT>::type;
|
||||
using Val = typename Src::value_type;
|
||||
using Iter = typename IterSource<Val>::iterator;
|
||||
using Src = std::remove_reference<IT>::type;
|
||||
using Val = Src::value_type;
|
||||
using Iter = IterSource<Val>::iterator;
|
||||
};
|
||||
|
||||
template<class IT, class FUN>
|
||||
struct _TransformIterT
|
||||
{
|
||||
using Src = typename std::remove_reference<IT>::type;
|
||||
using ResVal = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using Src = std::remove_reference<IT>::type;
|
||||
using ResVal = lib::meta::_Fun<FUN>::Ret;
|
||||
using TransIter = TransformIter<Src, ResVal>;
|
||||
using Iter = typename IterSource<ResVal>::iterator;
|
||||
using Iter = IterSource<ResVal>::iterator;
|
||||
};
|
||||
|
||||
template<class IT>
|
||||
struct _PairIterT
|
||||
{
|
||||
using Src = typename std::remove_reference<IT>::type;
|
||||
using PairType = typename Src::value_type;
|
||||
using ValType = typename PairType::second_type;
|
||||
using ConstKeyType = typename PairType::first_type;
|
||||
using Src = std::remove_reference<IT>::type;
|
||||
using PairType = Src::value_type;
|
||||
using ValType = PairType::second_type;
|
||||
using ConstKeyType = PairType::first_type;
|
||||
|
||||
// since we're returning the keys always by value,
|
||||
// we can strip the const added by the STL map types
|
||||
using KeyType = typename std::remove_const<ConstKeyType>::type;
|
||||
using KeyType = std::remove_const<ConstKeyType>::type;
|
||||
|
||||
using KeyIter = TransformIter<Src, KeyType>;
|
||||
using ValIter = TransformIter<Src, ValType>;
|
||||
|
|
@ -335,14 +335,14 @@ namespace lib {
|
|||
|
||||
|
||||
template<class IT>
|
||||
typename _PairIterT<IT>::KeyIter
|
||||
_PairIterT<IT>::KeyIter
|
||||
takePairFirst (IT&& source)
|
||||
{
|
||||
return transformIterator(forward<IT>(source), _PairIterT<IT>::takeFirst );
|
||||
}
|
||||
|
||||
template<class IT>
|
||||
typename _PairIterT<IT>::ValIter
|
||||
_PairIterT<IT>::ValIter
|
||||
takePairSecond (IT&& source)
|
||||
{
|
||||
return transformIterator(forward<IT>(source), _PairIterT<IT>::takeSecond );
|
||||
|
|
@ -356,11 +356,11 @@ namespace lib {
|
|||
* exposing just a IterSource based frontend.
|
||||
*/
|
||||
template<class IT>
|
||||
typename _IterT<IT>::Iter
|
||||
_IterT<IT>::Iter
|
||||
wrapIter (IT&& source)
|
||||
{
|
||||
using Src = typename _IterT<IT>::Src;
|
||||
using Val = typename _IterT<IT>::Val;
|
||||
using Src = _IterT<IT>::Src;
|
||||
using Val = _IterT<IT>::Val;
|
||||
|
||||
return IterSource<Val>::build (new WrappedLumieraIter<Src> (forward<IT>(source)));
|
||||
}
|
||||
|
|
@ -376,7 +376,7 @@ namespace lib {
|
|||
singleVal (VAL&& something)
|
||||
{
|
||||
using Src = decltype(singleValIterator (forward<VAL>(something)));
|
||||
using Val = typename _IterT<Src>::Val;
|
||||
using Val = _IterT<Src>::Val;
|
||||
|
||||
return IterSource<Val>::build (new WrappedLumieraIter<Src>{singleValIterator (forward<VAL>(something))});
|
||||
}
|
||||
|
|
@ -392,11 +392,11 @@ namespace lib {
|
|||
* function call for every fetched element.
|
||||
*/
|
||||
template<class IT, class FUN>
|
||||
typename _TransformIterT<IT,FUN>::Iter
|
||||
_TransformIterT<IT,FUN>::Iter
|
||||
transform (IT&& source, FUN processingFunc)
|
||||
{
|
||||
using ValType = typename _TransformIterT<IT,FUN>::ResVal;
|
||||
using TransIT = typename _TransformIterT<IT,FUN>::TransIter;
|
||||
using ValType = _TransformIterT<IT,FUN>::ResVal;
|
||||
using TransIT = _TransformIterT<IT,FUN>::TransIter;
|
||||
|
||||
return IterSource<ValType>::build (
|
||||
new WrappedLumieraIter<TransIT> (
|
||||
|
|
@ -408,7 +408,7 @@ namespace lib {
|
|||
* all the keys of the given Map or Hashtable
|
||||
*/
|
||||
template<class MAP>
|
||||
typename _MapT<MAP>::KeyIter
|
||||
_MapT<MAP>::KeyIter
|
||||
eachMapKey (MAP& map)
|
||||
{
|
||||
using Range = RangeIter<typename MAP::iterator>;
|
||||
|
|
@ -422,7 +422,7 @@ namespace lib {
|
|||
* all the values of the given Map or Hashtable
|
||||
*/
|
||||
template<class MAP>
|
||||
typename _MapT<MAP>::ValIter
|
||||
_MapT<MAP>::ValIter
|
||||
eachMapVal (MAP& map)
|
||||
{
|
||||
using Range = RangeIter<typename MAP::iterator>;
|
||||
|
|
@ -438,7 +438,7 @@ namespace lib {
|
|||
* the distinct keys
|
||||
*/
|
||||
template<class MAP>
|
||||
typename _MapT<MAP>::KeyIter
|
||||
_MapT<MAP>::KeyIter
|
||||
eachDistinctKey (MAP& map)
|
||||
{
|
||||
using Range = RangeIter<typename MAP::iterator>;
|
||||
|
|
@ -453,10 +453,10 @@ namespace lib {
|
|||
* @note obviously in case of a Map we'll get at most one result.
|
||||
*/
|
||||
template<class MAP>
|
||||
typename _MapT<MAP>::ValIter
|
||||
_MapT<MAP>::ValIter
|
||||
eachValForKey (MAP& map, typename _MapT<MAP>::Key key)
|
||||
{
|
||||
using Pos = typename MAP::iterator;
|
||||
using Pos = MAP::iterator;
|
||||
using Range = RangeIter<Pos>;
|
||||
|
||||
std::pair<Pos,Pos> valuesForKey = map.equal_range(key);
|
||||
|
|
@ -472,10 +472,10 @@ namespace lib {
|
|||
* starting with \c begin and excluding \c end .
|
||||
*/
|
||||
template<class CON>
|
||||
typename _SeqT<CON>::Iter
|
||||
_SeqT<CON>::Iter
|
||||
eachEntry (CON& container)
|
||||
{
|
||||
using ValType = typename _SeqT<CON>::Val;
|
||||
using ValType = _SeqT<CON>::Val;
|
||||
using Range = RangeIter<typename CON::iterator>;
|
||||
|
||||
Range contents (container.begin(), container.end());
|
||||
|
|
@ -487,10 +487,10 @@ namespace lib {
|
|||
* defined by a classical Iterator range.
|
||||
*/
|
||||
template<class IT>
|
||||
typename _RangeT<IT>::Iter
|
||||
_RangeT<IT>::Iter
|
||||
eachEntry (IT const& begin, IT const& end)
|
||||
{
|
||||
using ValType = typename _RangeT<IT>::Val;
|
||||
using ValType = _RangeT<IT>::Val;
|
||||
using Range = RangeIter<IT>;
|
||||
|
||||
Range contents (begin, end);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace lib {
|
|||
* Building block for a tupeled-iterator.
|
||||
* exposes the iterator API lifted to the product type (tuple).
|
||||
*/
|
||||
template<class ITUP>
|
||||
template<meta::tuple_like ITUP>
|
||||
class ProductCore
|
||||
{
|
||||
ITUP iters_;
|
||||
|
|
@ -76,8 +76,8 @@ namespace lib {
|
|||
bool
|
||||
checkPoint() const
|
||||
{ //note: short-circuit
|
||||
return std::apply ([](auto&... its) { return (bool(its) and ...); }
|
||||
, iters_);
|
||||
return meta::apply ([](auto&... its) { return (bool(its) and ...); }
|
||||
, iters_);
|
||||
}
|
||||
|
||||
ITUP&
|
||||
|
|
@ -137,7 +137,7 @@ namespace lib {
|
|||
inline auto
|
||||
zip (ITS&& ...iters)
|
||||
{
|
||||
auto access_result = [](auto& it)->decltype(auto){ return *it; }; // Note: pass-through result type (maybe reference)
|
||||
auto access_result = [ ](auto& it)->decltype(auto){ return *it; }; // Note: pass-through result type (maybe reference)
|
||||
auto tuple_results = [&](auto& it){ return meta::mapEach (*it, access_result); };
|
||||
//
|
||||
auto core = iter::ProductCore{iter::buildIterTuple (std::forward<ITS> (iters)...)};
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ namespace lib {
|
|||
return bool(source_);
|
||||
}
|
||||
|
||||
using pointer = typename IT::pointer;
|
||||
using reference = typename IT::reference;
|
||||
using value_type = typename IT::value_type;
|
||||
using pointer = IT::pointer;
|
||||
using reference = IT::reference;
|
||||
using value_type = IT::value_type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -186,9 +186,9 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
using pointer = typename CORE::pointer;
|
||||
using reference = typename CORE::reference;
|
||||
using value_type = typename CORE::value_type;
|
||||
using pointer = CORE::pointer;
|
||||
using reference = CORE::reference;
|
||||
using value_type = CORE::value_type;
|
||||
|
||||
|
||||
IterTool (CORE&& setup)
|
||||
|
|
@ -341,7 +341,7 @@ namespace lib {
|
|||
typedef IterTool<_Filter> _Impl;
|
||||
|
||||
public:
|
||||
static bool acceptAll(typename _Filter::Val) { return true; }
|
||||
static bool acceptAll(_Filter::Val) { return true; }
|
||||
|
||||
|
||||
FilterIter ()
|
||||
|
|
@ -378,7 +378,7 @@ namespace lib {
|
|||
inline auto
|
||||
filterIterator (IT&& src, PRED filterPredicate)
|
||||
{
|
||||
using SrcIT = typename std::remove_reference<IT>::type;
|
||||
using SrcIT = std::remove_reference<IT>::type;
|
||||
return FilterIter<SrcIT>{forward<IT>(src), filterPredicate};
|
||||
}
|
||||
|
||||
|
|
@ -411,7 +411,7 @@ namespace lib {
|
|||
: public FilterIter<IT>
|
||||
{
|
||||
using _Filter = FilterCore<IT>;
|
||||
using Val = typename _Filter::Val;
|
||||
using Val = _Filter::Val;
|
||||
|
||||
void
|
||||
reEvaluate()
|
||||
|
|
@ -739,9 +739,9 @@ namespace lib {
|
|||
return bool(source_);
|
||||
}
|
||||
|
||||
using pointer = typename ValueTypeBinding<VAL>::pointer;
|
||||
using reference = typename ValueTypeBinding<VAL>::reference;
|
||||
using value_type = typename ValueTypeBinding<VAL>::value_type;
|
||||
using pointer = ValueTypeBinding<VAL>::pointer;
|
||||
using reference = ValueTypeBinding<VAL>::reference;
|
||||
using value_type = ValueTypeBinding<VAL>::value_type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -787,7 +787,7 @@ namespace lib {
|
|||
inline auto
|
||||
transformIterator (IT const& src, FUN processingFunc)
|
||||
{
|
||||
using OutVal = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using OutVal = lib::meta::_Fun<FUN>::Ret;
|
||||
return TransformIter<IT,OutVal>{src,processingFunc};
|
||||
}
|
||||
|
||||
|
|
@ -795,8 +795,8 @@ namespace lib {
|
|||
inline auto
|
||||
transformIterator (IT&& src, FUN processingFunc)
|
||||
{
|
||||
using SrcIT = typename std::remove_reference<IT>::type;
|
||||
using OutVal = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using SrcIT = std::remove_reference<IT>::type;
|
||||
using OutVal = lib::meta::_Fun<FUN>::Ret;
|
||||
return TransformIter<SrcIT,OutVal>{forward<IT>(src), processingFunc};
|
||||
}
|
||||
|
||||
|
|
@ -815,10 +815,10 @@ namespace lib {
|
|||
|
||||
|
||||
template<class IT>
|
||||
inline typename IT::value_type
|
||||
inline IT::value_type
|
||||
pull_last (IT iter)
|
||||
{
|
||||
using Val = typename IT::value_type;
|
||||
using Val = IT::value_type;
|
||||
using Item = wrapper::ItemWrapper<Val>;
|
||||
|
||||
Item lastElm;
|
||||
|
|
@ -845,7 +845,7 @@ namespace lib {
|
|||
inline auto
|
||||
filterRepetitions (IT const& source)
|
||||
{
|
||||
using Val = typename meta::ValueTypeBinding<IT>::value_type;
|
||||
using Val = meta::ValueTypeBinding<IT>::value_type;
|
||||
return filterIterator (source, SkipRepetition<Val>());
|
||||
}
|
||||
|
||||
|
|
@ -853,7 +853,7 @@ namespace lib {
|
|||
inline auto
|
||||
filterRepetitions (IT&& source)
|
||||
{
|
||||
using Val = typename meta::ValueTypeBinding<IT>::value_type;
|
||||
using Val = meta::ValueTypeBinding<IT>::value_type;
|
||||
return filterIterator (forward<IT>(source), SkipRepetition<Val>() );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ namespace lib {
|
|||
generateTrap (DEL* delegate)
|
||||
{
|
||||
static_assert (_Fun<DEL>(), "Delegate must be function-like");
|
||||
using Ret = typename _Fun<DEL>::Ret;
|
||||
using Ret = _Fun<DEL>::Ret;
|
||||
static_assert (_Fun<Ret>(), "Result from invoking delegate must also be function-like");
|
||||
static_assert (has_Sig<Ret, SIG>(), "Result from delegate must expose target signature");
|
||||
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ namespace lumiera {
|
|||
|
||||
|
||||
|
||||
const char * ON_BASIC_INIT ("ON_BASIC_INIT");
|
||||
const char * ON_GLOBAL_INIT ("ON_GLOBAL_INIT");
|
||||
const char * ON_GLOBAL_SHUTDOWN ("ON_GLOBAL_SHUTDOWN");
|
||||
CStr ON_BASIC_INIT ("ON_BASIC_INIT");
|
||||
CStr ON_GLOBAL_INIT ("ON_GLOBAL_INIT");
|
||||
CStr ON_GLOBAL_SHUTDOWN ("ON_GLOBAL_SHUTDOWN");
|
||||
|
||||
const char * ON_EMERGENCY ("ON_EMERGENCY");
|
||||
CStr ON_EMERGENCY ("ON_EMERGENCY");
|
||||
|
||||
|
||||
} // namespace lumiera
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ namespace lib {
|
|||
* discarding of node elements
|
||||
*/
|
||||
explicit
|
||||
LinkedElements (typename ALO::CustomAllocator allo)
|
||||
LinkedElements (ALO::CustomAllocator allo)
|
||||
: ALO{allo}
|
||||
, head_{nullptr}
|
||||
{ }
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@
|
|||
{ \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(typename X::_TYPE_ *); \
|
||||
static Yes_t check(X::_TYPE_ *); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
|
|
@ -183,30 +183,30 @@
|
|||
* and return type. Yet a non-function member will not trigger this detector.
|
||||
* @note this check will fail if there are overloads or similar ambiguity
|
||||
*/
|
||||
#define META_DETECT_FUNCTION_NAME(_FUN_NAME_) \
|
||||
template<typename TY> \
|
||||
class HasFunName_##_FUN_NAME_ \
|
||||
{ \
|
||||
template<typename SEL> \
|
||||
struct Probe; \
|
||||
template<class C, typename RET, typename...ARGS> \
|
||||
struct Probe<RET (C::*) (ARGS...)> \
|
||||
{ \
|
||||
using Match = void; \
|
||||
}; \
|
||||
template<class C, typename RET, typename...ARGS> \
|
||||
struct Probe<RET (C::*) (ARGS...) const> \
|
||||
{ \
|
||||
using Match = void; \
|
||||
}; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(typename Probe<decltype(&X::_FUN_NAME_)>::Match * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
#define META_DETECT_FUNCTION_NAME(_FUN_NAME_) \
|
||||
template<typename TY> \
|
||||
class HasFunName_##_FUN_NAME_ \
|
||||
{ \
|
||||
template<typename SEL> \
|
||||
struct Probe; \
|
||||
template<class C, typename RET, typename...ARGS> \
|
||||
struct Probe<RET (C::*) (ARGS...)> \
|
||||
{ \
|
||||
using Match = void; \
|
||||
}; \
|
||||
template<class C, typename RET, typename...ARGS> \
|
||||
struct Probe<RET (C::*) (ARGS...) const> \
|
||||
{ \
|
||||
using Match = void; \
|
||||
}; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(Probe<decltype(&X::_FUN_NAME_)>::Match * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -216,22 +216,22 @@
|
|||
* @remarks the presence of overloads is irrelevant, since we explicitly
|
||||
* from an invocation to that function (within `decltype`)
|
||||
*/
|
||||
#define META_DETECT_FUNCTION_ARGLESS(_FUN_) \
|
||||
template<typename TY> \
|
||||
class HasArglessFun_##_FUN_ \
|
||||
{ \
|
||||
template<typename X, \
|
||||
#define META_DETECT_FUNCTION_ARGLESS(_FUN_) \
|
||||
template<typename TY> \
|
||||
class HasArglessFun_##_FUN_ \
|
||||
{ \
|
||||
template<typename X, \
|
||||
typename SEL = decltype(std::declval<X>()._FUN_())>\
|
||||
struct Probe \
|
||||
{ }; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(Probe<X> * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
struct Probe \
|
||||
{ }; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(Probe<X> * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -245,22 +245,22 @@
|
|||
* type checks, the extension point is assumed to be supported.
|
||||
* @warning beware of implicit type conversions
|
||||
*/
|
||||
#define META_DETECT_EXTENSION_POINT(_FUN_) \
|
||||
template<typename TY> \
|
||||
class HasExtensionPoint_##_FUN_ \
|
||||
{ \
|
||||
template<typename X, \
|
||||
#define META_DETECT_EXTENSION_POINT(_FUN_) \
|
||||
template<typename TY> \
|
||||
class HasExtensionPoint_##_FUN_ \
|
||||
{ \
|
||||
template<typename X, \
|
||||
typename SEL = decltype( _FUN_(std::declval<X>()))>\
|
||||
struct Probe \
|
||||
{ }; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(Probe<X> * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
struct Probe \
|
||||
{ }; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(Probe<X> * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ namespace func{
|
|||
template<typename X, typename TAIL, size_t i>
|
||||
struct PlaceholderTuple<Node<X,TAIL>, i>
|
||||
{
|
||||
using TailPlaceholders = typename PlaceholderTuple<TAIL,i+1>::List;
|
||||
using TailPlaceholders = PlaceholderTuple<TAIL,i+1>::List;
|
||||
|
||||
using List = Node<_Placeholder<i>, TailPlaceholders>;
|
||||
};
|
||||
|
|
@ -136,7 +136,7 @@ namespace func{
|
|||
struct PartiallyInitTuple
|
||||
{
|
||||
template<size_t i>
|
||||
using DestType = typename std::tuple_element_t<i, TAR>;
|
||||
using DestType = std::tuple_element_t<i, TAR>;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -230,17 +230,17 @@ namespace func{
|
|||
* argument positions marked with `std::_Placeholder<N>` instances
|
||||
* will remain _open_ to accept arguments on the resulting function.
|
||||
*/
|
||||
template<class FUN, class TUP, typename = enable_if_Tuple<TUP>>
|
||||
template<class FUN, class TUP> requires(tuple_like<remove_reference_t<TUP>>)
|
||||
auto
|
||||
bindArgTuple (FUN&& fun, TUP&& tuple)
|
||||
{
|
||||
return std::apply ([functor = forward<FUN>(fun)]
|
||||
(auto&&... args)
|
||||
{
|
||||
return std::bind (move(functor)
|
||||
,forward<decltype(args)> (args) ...);
|
||||
}
|
||||
,std::forward<TUP> (tuple));
|
||||
return lib::meta::apply ([functor = forward<FUN>(fun)]
|
||||
(auto&&... args)
|
||||
{
|
||||
return std::bind (move(functor)
|
||||
,forward<decltype(args)> (args) ...);
|
||||
}
|
||||
,std::forward<TUP> (tuple));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -257,8 +257,8 @@ namespace func{
|
|||
buildInvokableWrapper (FUN&& fun)
|
||||
{
|
||||
static_assert (is_Typelist<TYPES>::value);
|
||||
using ArgTypes = typename TYPES::Seq;
|
||||
using Builder = typename lib::meta::RebindVariadic<AdaptInvokable, ArgTypes>::Type;
|
||||
using ArgTypes = TYPES::Seq;
|
||||
using Builder = lib::meta::RebindVariadic<AdaptInvokable, ArgTypes>::Type;
|
||||
|
||||
return Builder::buildWrapper (forward<FUN> (fun));
|
||||
}
|
||||
|
|
@ -290,11 +290,11 @@ namespace func{
|
|||
template<typename SIG, typename VAL>
|
||||
class PApply
|
||||
{
|
||||
using Args = typename _Fun<SIG>::Args;
|
||||
using Ret = typename _Fun<SIG>::Ret;
|
||||
using ArgsList = typename Args::List;
|
||||
using ValList = typename VAL::List;
|
||||
using ValTypes = typename Types<ValList>::Seq; // reconstruct a type-seq from a type-list
|
||||
using Args = _Fun<SIG>::Args;
|
||||
using Ret = _Fun<SIG>::Ret;
|
||||
using ArgsList = Args::List;
|
||||
using ValList = VAL::List;
|
||||
using ValTypes = Types<ValList>::Seq; // reconstruct a type-seq from a type-list
|
||||
|
||||
enum { ARG_CNT = count<ArgsList>()
|
||||
, VAL_CNT = count<ValList>()
|
||||
|
|
@ -303,34 +303,34 @@ namespace func{
|
|||
|
||||
|
||||
// create list of the *remaining* arguments, after applying the ValList
|
||||
using LeftReduced = typename Splice<ArgsList, ValList>::Back;
|
||||
using RightReduced = typename Splice<ArgsList, ValList, ROFFSET>::Front;
|
||||
using LeftReduced = Splice<ArgsList, ValList>::Back;
|
||||
using RightReduced = Splice<ArgsList, ValList, ROFFSET>::Front;
|
||||
|
||||
using ArgsL = typename Types<LeftReduced>::Seq;
|
||||
using ArgsR = typename Types<RightReduced>::Seq;
|
||||
using ArgsL = Types<LeftReduced>::Seq;
|
||||
using ArgsR = Types<RightReduced>::Seq;
|
||||
|
||||
|
||||
// build a list, where each of the *remaining* arguments is replaced by a placeholder marker
|
||||
using TrailingPlaceholders = typename func::PlaceholderTuple<LeftReduced>::List;
|
||||
using LeadingPlaceholders = typename func::PlaceholderTuple<RightReduced>::List;
|
||||
using TrailingPlaceholders = func::PlaceholderTuple<LeftReduced>::List;
|
||||
using LeadingPlaceholders = func::PlaceholderTuple<RightReduced>::List;
|
||||
|
||||
// ... and splice these placeholders on top of the original argument type list,
|
||||
// thus retaining the types to be closed, but setting a placeholder for each remaining argument
|
||||
using LeftReplaced = typename Splice<ArgsList, TrailingPlaceholders, VAL_CNT>::List;
|
||||
using RightReplaced = typename Splice<ArgsList, LeadingPlaceholders, 0 >::List;
|
||||
using LeftReplaced = Splice<ArgsList, TrailingPlaceholders, VAL_CNT>::List;
|
||||
using RightReplaced = Splice<ArgsList, LeadingPlaceholders, 0 >::List;
|
||||
|
||||
using LeftReplacedTypes = typename Types<LeftReplaced>::Seq;
|
||||
using RightReplacedTypes = typename Types<RightReplaced>::Seq;
|
||||
using LeftReplacedTypes = Types<LeftReplaced>::Seq;
|
||||
using RightReplacedTypes = Types<RightReplaced>::Seq;
|
||||
|
||||
// create a "builder" helper, which accepts exactly the value tuple elements
|
||||
// and puts them at the right location, while default-constructing the remaining
|
||||
// (=placeholder)-arguments. Using this builder helper, we can finally set up
|
||||
// the argument tuples (Left/RightReplacedArgs) used for the std::bind call
|
||||
template<class SRC, class TAR, size_t i>
|
||||
using IdxSelectorL = typename PartiallyInitTuple<SRC, TAR, 0>::template IndexMapper<i>;
|
||||
using IdxSelectorL = PartiallyInitTuple<SRC, TAR, 0>::template IndexMapper<i>;
|
||||
|
||||
template<class SRC, class TAR, size_t i>
|
||||
using IdxSelectorR = typename PartiallyInitTuple<SRC, TAR, ROFFSET>::template IndexMapper<i>;
|
||||
using IdxSelectorR = PartiallyInitTuple<SRC, TAR, ROFFSET>::template IndexMapper<i>;
|
||||
|
||||
using BuildL = TupleConstructor<LeftReplacedTypes, IdxSelectorL>;
|
||||
using BuildR = TupleConstructor<RightReplacedTypes, IdxSelectorR>;
|
||||
|
|
@ -404,31 +404,31 @@ namespace func{
|
|||
template<typename SIG, typename X, uint pos>
|
||||
class BindToArgument
|
||||
{
|
||||
using Args = typename _Fun<SIG>::Args;
|
||||
using Ret = typename _Fun<SIG>::Ret;
|
||||
using ArgsList = typename Args::List;
|
||||
using ValList = typename Types<X>::List;
|
||||
using Args = _Fun<SIG>::Args;
|
||||
using Ret = _Fun<SIG>::Ret;
|
||||
using ArgsList = Args::List;
|
||||
using ValList = Types<X>::List;
|
||||
|
||||
enum { ARG_CNT = count<ArgsList>() };
|
||||
|
||||
using RemainingFront = typename Splice<ArgsList, ValList, pos>::Front;
|
||||
using RemainingBack = typename Splice<ArgsList, ValList, pos>::Back;
|
||||
using PlaceholdersBefore = typename func::PlaceholderTuple<RemainingFront>::List;
|
||||
using PlaceholdersBehind = typename func::PlaceholderTuple<RemainingBack,pos+1>::List;
|
||||
using RemainingFront = Splice<ArgsList, ValList, pos>::Front;
|
||||
using RemainingBack = Splice<ArgsList, ValList, pos>::Back;
|
||||
using PlaceholdersBefore = func::PlaceholderTuple<RemainingFront>::List;
|
||||
using PlaceholdersBehind = func::PlaceholderTuple<RemainingBack,pos+1>::List;
|
||||
|
||||
using PreparedArgsRaw = typename Append<typename Append<PlaceholdersBefore // arguments before the splice: passed-through
|
||||
,ValList >::List // splice in the value tuple
|
||||
,PlaceholdersBehind // arguments behind the splice: passed-through
|
||||
>::List;
|
||||
using PreparedArgs = Prefix<PreparedArgsRaw, ARG_CNT>;
|
||||
using ReducedArgs = typename Append<RemainingFront, RemainingBack>::List;
|
||||
using ReducedArgs = Append<RemainingFront, RemainingBack>::List;
|
||||
|
||||
using PreparedArgTypes = typename Types<PreparedArgs>::Seq;
|
||||
using RemainingArgs = typename Types<ReducedArgs>::Seq;
|
||||
using PreparedArgTypes = Types<PreparedArgs>::Seq;
|
||||
using RemainingArgs = Types<ReducedArgs>::Seq;
|
||||
|
||||
|
||||
template<class SRC, class TAR, size_t i>
|
||||
using IdxSelector = typename PartiallyInitTuple<SRC, TAR, pos>::template IndexMapper<i>;
|
||||
using IdxSelector = PartiallyInitTuple<SRC, TAR, pos>::template IndexMapper<i>;
|
||||
|
||||
using BuildPreparedArgs = TupleConstructor<PreparedArgTypes, IdxSelector>;
|
||||
|
||||
|
|
@ -461,10 +461,10 @@ namespace func{
|
|||
template<typename FUN1, typename FUN2>
|
||||
struct _Chain
|
||||
{
|
||||
using Ret = typename _Fun<FUN2>::Ret;
|
||||
using Args = typename _Fun<FUN1>::Args;
|
||||
using Ret = _Fun<FUN2>::Ret;
|
||||
using Args = _Fun<FUN1>::Args;
|
||||
|
||||
using FunType = typename BuildFunType<Ret,Args>::Fun;
|
||||
using FunType = BuildFunType<Ret,Args>::Fun;
|
||||
static auto adaptedFunType() { return FunType{}; }
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ namespace meta{
|
|||
|
||||
/** abbreviation for referring to a function's return type */
|
||||
template<typename FUN>
|
||||
using _FunRet = typename _Fun<FUN>::Ret;
|
||||
using _FunRet = _Fun<FUN>::Ret;
|
||||
|
||||
namespace {
|
||||
template<typename FUN>
|
||||
|
|
@ -259,14 +259,14 @@ namespace meta{
|
|||
static_assert(_Fun<FUN>() , "something funktion-like required");
|
||||
static_assert(_Fun<FUN>::ARITY == 1 , "function with exactly one argument required");
|
||||
|
||||
using Sig = typename _Fun<FUN>::Sig;
|
||||
using Arg = typename _Fun<Sig>::Args::List::Head;
|
||||
using Sig = _Fun<FUN>::Sig;
|
||||
using Arg = _Fun<Sig>::Args::List::Head;
|
||||
};
|
||||
}
|
||||
|
||||
/** abbreviation for referring to a function's single Argument type */
|
||||
template<typename FUN>
|
||||
using _FunArg = typename _DetectSingleArgFunction<FUN>::Arg;
|
||||
using _FunArg = _DetectSingleArgFunction<FUN>::Arg;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ namespace meta {
|
|||
* reference to an anonymous temporary.
|
||||
*/
|
||||
template<typename X>
|
||||
typename Unwrap<X>::Type&
|
||||
Unwrap<X>::Type&
|
||||
unwrap (X const& wrapped)
|
||||
{
|
||||
return Unwrap<X>::extract(wrapped);
|
||||
|
|
@ -258,7 +258,7 @@ namespace meta {
|
|||
using TypePointee = remove_pointer_t<TypeReferred>;
|
||||
using TypePlain = remove_cv_t<TypePointee>;
|
||||
|
||||
using Type = typename Unwrap<TypePlain>::Type;
|
||||
using Type = Unwrap<TypePlain>::Type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -509,7 +509,7 @@ namespace meta {
|
|||
template<typename T>
|
||||
class can_IterForEach
|
||||
{
|
||||
using Type = typename Strip<T>::Type;
|
||||
using Type = Strip<T>::Type;
|
||||
|
||||
META_DETECT_NESTED(value_type);
|
||||
META_DETECT_OPERATOR_DEREF();
|
||||
|
|
@ -533,7 +533,7 @@ namespace meta {
|
|||
template<typename T>
|
||||
class is_StateCore
|
||||
{
|
||||
using Type = typename Strip<T>::Type;
|
||||
using Type = Strip<T>::Type;
|
||||
|
||||
META_DETECT_FUNCTION_ARGLESS(checkPoint);
|
||||
META_DETECT_FUNCTION_ARGLESS(iterNext);
|
||||
|
|
@ -554,7 +554,7 @@ namespace meta {
|
|||
template<typename T>
|
||||
class can_STL_ForEach
|
||||
{
|
||||
using Type = typename Strip<T>::Type;
|
||||
using Type = Strip<T>::Type;
|
||||
|
||||
struct is_iterable
|
||||
{
|
||||
|
|
@ -618,7 +618,7 @@ namespace meta {
|
|||
template<typename T>
|
||||
class can_STL_backIteration
|
||||
{
|
||||
using Type = typename Strip<T>::Type;
|
||||
using Type = Strip<T>::Type;
|
||||
|
||||
struct is_backIterable
|
||||
{
|
||||
|
|
|
|||
|
|
@ -133,15 +133,15 @@ namespace meta{
|
|||
static auto
|
||||
wrapBuilder (CLO closureFun) ///< need to provide the remaining arguments as a tuple
|
||||
{
|
||||
using RemainingArgs = typename _Fun<CLO>::Args;
|
||||
using RemainingParams = typename lib::meta::RebindVariadic<TUP, RemainingArgs>::Type;
|
||||
using RemainingArgs = _Fun<CLO>::Args;
|
||||
using RemainingParams = lib::meta::RebindVariadic<TUP, RemainingArgs>::Type;
|
||||
|
||||
struct Wrap
|
||||
{
|
||||
auto
|
||||
operator() (RemainingParams remPar) const
|
||||
{
|
||||
return apply (unConst(this)->partialClosure_, remPar);
|
||||
return lib::meta::apply (unConst(this)->partialClosure_, remPar);
|
||||
};
|
||||
|
||||
CLO partialClosure_;
|
||||
|
|
@ -186,13 +186,13 @@ namespace meta{
|
|||
template<typename T, size_t N>
|
||||
struct _Adapt
|
||||
{
|
||||
using NFold = typename Repeat<T,N>::Seq;
|
||||
using Array = typename RebindVariadic<ArrayAdapt, NFold>::Type;
|
||||
using NFold = Repeat<T,N>::Seq;
|
||||
using Array = RebindVariadic<ArrayAdapt, NFold>::Type;
|
||||
static_assert(N,"attempt to partially close empty array");
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
using _AdaptArray_t = typename _Adapt<T,N>::Array;
|
||||
using _AdaptArray_t = _Adapt<T,N>::Array;
|
||||
}
|
||||
|
||||
/** @note adding seamless conversion and compount-init */
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
** to the tuple type provided by the standard library, including traits and
|
||||
** helpers to build tuple types from metaprogramming and to pretty-print tuples.
|
||||
**
|
||||
** Notably, a `concept tuple_like` is provided, which is satisfied for any type in compliance
|
||||
** with the »tuple protocol«. Together with a [generic accessor][\ref lib::meta::getElm),
|
||||
** this allows to handle all _tuple-like_ types uniformly.
|
||||
** @note Due to an unfortunate limitation of the standard, we're forced to provide our own alternative
|
||||
** implementation to replace `std::apply`, so that a function can be applied to any _tuple-like_
|
||||
**
|
||||
** Furthermore, a generic iteration construct is provided, to instantiate
|
||||
** a generic Lambda for each element of a given tuple, which allows to write
|
||||
** generic code »for each tuple element«.
|
||||
|
|
@ -71,12 +77,87 @@ namespace meta {
|
|||
struct is_Tuple<const std::tuple<TYPES...>>
|
||||
: std::true_type
|
||||
{ };
|
||||
|
||||
|
||||
using std::remove_cv_t;
|
||||
using std::is_reference_v;
|
||||
using std::remove_reference_t;
|
||||
|
||||
|
||||
/** @internal building-block: a type supporting the `tuple_size` metafunction */
|
||||
template<class TUP>
|
||||
using enable_if_Tuple = lib::meta::enable_if<lib::meta::is_Tuple<std::remove_reference_t<TUP>>>;
|
||||
|
||||
concept tuple_sized = requires
|
||||
{
|
||||
{ std::tuple_size<TUP>::value } -> std::convertible_to<size_t>;
|
||||
};
|
||||
|
||||
|
||||
/** @internal building-block: a type where elements can be accessed through a `get` friend function */
|
||||
template<class TUP, std::size_t idx>
|
||||
concept tuple_adl_accessible = requires(TUP tup)
|
||||
{
|
||||
typename std::tuple_element_t<idx, TUP>;
|
||||
{ get<idx>(tup) } -> std::convertible_to<std::tuple_element_t<idx, TUP>&>;
|
||||
};
|
||||
|
||||
/** @internal building-block: a type where elements can be accessed through a `get` member function */
|
||||
template<class TUP, std::size_t idx>
|
||||
concept tuple_mem_accessible = requires(TUP tup)
|
||||
{
|
||||
typename std::tuple_element_t<idx, TUP>;
|
||||
{ tup.template get<idx>() } -> std::convertible_to<std::tuple_element_t<idx, TUP>&>;
|
||||
};
|
||||
|
||||
template<class TUP, std::size_t idx>
|
||||
concept tuple_element_accessible = tuple_mem_accessible<TUP,idx> or tuple_adl_accessible<TUP,idx>;
|
||||
|
||||
template<class TUP>
|
||||
using disable_if_Tuple = lib::meta::disable_if<lib::meta::is_Tuple<std::remove_reference_t<TUP>>>;
|
||||
concept tuple_accessible =
|
||||
tuple_sized<TUP> and
|
||||
WithIdxSeq<std::tuple_size_v<TUP>>::andAll([](auto idx)
|
||||
{
|
||||
return tuple_element_accessible<TUP,idx>;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Concept to mark any type compliant to the »tuple protocol«
|
||||
*/
|
||||
template<class TUP>
|
||||
concept tuple_like = not is_reference_v<TUP>
|
||||
and tuple_sized<remove_cv_t<TUP>>
|
||||
and tuple_accessible<remove_cv_t<TUP>>;
|
||||
|
||||
|
||||
/**
|
||||
* Helper for abstracted / unified access to member elements of any _tuple-like_
|
||||
* @remark preferably uses a `get<i>` member function, falling back to a
|
||||
* free function `get`, which is found by ADL.
|
||||
*/
|
||||
template<std::size_t idx, class TUP>
|
||||
requires(tuple_like<std::remove_reference_t<TUP>>)
|
||||
decltype(auto)
|
||||
getElm (TUP&& tup)
|
||||
{
|
||||
using Tup = std::remove_reference_t<TUP>;
|
||||
static_assert (0 < std::tuple_size_v<Tup>);
|
||||
if constexpr (tuple_mem_accessible<Tup,0>)
|
||||
{
|
||||
if constexpr (std::is_reference_v<TUP>)
|
||||
return tup.template get<idx>();
|
||||
else
|
||||
{ // return value copy when tuple given as RValue
|
||||
using Elm = std::tuple_element_t<idx, TUP>;
|
||||
Elm elm(tup.template get<idx>());
|
||||
return elm;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // ▽▽▽ ADL
|
||||
using std::get;
|
||||
return get<idx> (std::forward<TUP> (tup));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -86,22 +167,29 @@ namespace meta {
|
|||
template<typename FUN, typename TUP, size_t...Idx>
|
||||
constexpr decltype(auto)
|
||||
__unpack_and_apply (FUN&& f, TUP&& tup, std::index_sequence<Idx...>)
|
||||
{ // ▽▽▽ ADL
|
||||
using std::get;
|
||||
{
|
||||
return std::invoke (std::forward<FUN> (f)
|
||||
,get<Idx> (std::forward<TUP>(tup))...
|
||||
,getElm<Idx> (std::forward<TUP>(tup))...
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** @internal invoke a metafunction with \a FUN and all element types from \a TUP */
|
||||
/** @internal invoke a metafunction with \a FUN and all element types from the _tuple-like_ \a TUP */
|
||||
template<template<typename...> class META, class FUN, class TUP>
|
||||
struct _InvokeMetafunTup
|
||||
{
|
||||
using Tupl = std::decay_t<TUP>;
|
||||
using Elms = typename ElmTypes<Tupl>::Seq;
|
||||
using Args = typename Prepend<FUN, Elms>::Seq;
|
||||
using Type = typename RebindVariadic<META, Args>::Type;
|
||||
using Elms = ElmTypes<Tupl>::Seq;
|
||||
using Args = Prepend<FUN, Elms>::Seq;
|
||||
using Type = RebindVariadic<META, Args>::Type;
|
||||
};
|
||||
template<template<typename...> class META, class FUN, class TUP>
|
||||
struct _InvokeMetafunTup<META, FUN, TUP&>
|
||||
{
|
||||
using Tupl = std::decay_t<TUP>;
|
||||
using Elms = typename ElmTypes<Tupl>::template Apply<std::add_lvalue_reference_t>;
|
||||
using Args = Prepend<FUN, Elms>::Seq;
|
||||
using Type = RebindVariadic<META, Args>::Type;
|
||||
};
|
||||
|
||||
template<class FUN, class TUP>
|
||||
|
|
@ -116,7 +204,7 @@ namespace meta {
|
|||
* @todo 6/2025 as a first step, this replicates the implementation from C++17;
|
||||
* the second step would be to constrain this to a concept `tuple_like`
|
||||
*/
|
||||
template<class FUN, class TUP>
|
||||
template<class FUN, class TUP> requires(tuple_like<remove_reference_t<TUP>>)
|
||||
constexpr decltype(auto)
|
||||
apply (FUN&& f, TUP&& tup) noexcept (can_nothrow_invoke_tup<FUN,TUP> )
|
||||
{
|
||||
|
|
@ -137,15 +225,15 @@ namespace meta {
|
|||
* std::apply to unpack the tuple's contents into an argument pack and
|
||||
* then employ a fold expression with the comma operator.
|
||||
*/
|
||||
template<class TUP, class FUN, typename = enable_if_Tuple<TUP>>
|
||||
template<class TUP, class FUN> requires(tuple_like<remove_reference_t<TUP>>)
|
||||
constexpr void
|
||||
forEach (TUP&& tuple, FUN fun)
|
||||
{
|
||||
std::apply ([&fun](auto&&... elms)
|
||||
{
|
||||
(fun (std::forward<decltype(elms)> (elms)), ...);
|
||||
}
|
||||
,std::forward<TUP> (tuple));
|
||||
lib::meta::apply ([&fun]<typename...ELMS>(ELMS&&... elms)
|
||||
{
|
||||
(fun (std::forward<ELMS>(elms)), ...);
|
||||
}
|
||||
,std::forward<TUP> (tuple));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -162,20 +250,56 @@ namespace meta {
|
|||
* Notably this differs from #forEach, where a fold-expression with comma-operator
|
||||
* is used, which is guaranteed to evaluate from left to right.
|
||||
*/
|
||||
template<class TUP, class FUN, typename = enable_if_Tuple<TUP>>
|
||||
template<class TUP, class FUN> requires(tuple_like<remove_reference_t<TUP>>)
|
||||
constexpr auto
|
||||
mapEach (TUP&& tuple, FUN fun)
|
||||
{
|
||||
return std::apply ([&fun](auto&&... elms)
|
||||
{ //..construct the type explicitly (make_tuple would decay fun result types)
|
||||
using Tuple = std::tuple<decltype(fun (std::forward<decltype(elms)> (elms))) ...>;
|
||||
return Tuple (fun (std::forward<decltype(elms)> (elms)) ...);
|
||||
}
|
||||
,std::forward<TUP> (tuple));
|
||||
return lib::meta::apply ([&fun]<typename...ELMS>(ELMS&&... elms)
|
||||
{ //..construct the type explicitly (make_tuple would decay fun result types)
|
||||
using Tuple = std::tuple<decltype(fun (std::forward<ELMS>(elms))) ...>;
|
||||
return Tuple (fun (std::forward<ELMS>(elms)) ...);
|
||||
}
|
||||
,std::forward<TUP> (tuple));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specialisation of variadic access for any tuple-like
|
||||
* @see variadic-helper.hpp
|
||||
*/
|
||||
template<tuple_like TUP>
|
||||
struct ElmTypes<TUP>
|
||||
{
|
||||
template<typename>
|
||||
struct Extract;
|
||||
template<size_t...idx>
|
||||
struct Extract<std::index_sequence<idx...>>
|
||||
{
|
||||
using ElmTypes = Types<std::tuple_element_t<idx,TUP> ...>;
|
||||
};
|
||||
|
||||
static constexpr size_t SIZ = std::tuple_size_v<TUP>;
|
||||
|
||||
using Idx = std::make_index_sequence<SIZ>;
|
||||
using Seq = Extract<Idx>::ElmTypes;
|
||||
using Tup = RebindVariadic<std::tuple, Seq>::Type;
|
||||
|
||||
template<template<class> class META>
|
||||
using Apply = ElmTypes<Seq>::template Apply<META>;
|
||||
|
||||
template<template<typename...> class O>
|
||||
using Rebind = RebindVariadic<O, Seq>::Type;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using AndAll = ElmTypes<Apply<PRED>>::template Rebind<std::__and_>;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using OrAll = ElmTypes<Apply<PRED>>::template Rebind<std::__or_>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace { // rebinding helper to create std::tuple from a type sequence
|
||||
|
|
@ -194,8 +318,8 @@ namespace meta {
|
|||
template<class H, typename TAIL>
|
||||
struct BuildTupleType<Node<H, TAIL>>
|
||||
{
|
||||
using Seq = typename Types<Node<H,TAIL>>::Seq;
|
||||
using Type = typename BuildTupleType<Seq>::Type;
|
||||
using Seq = Types<Node<H,TAIL>>::Seq;
|
||||
using Type = BuildTupleType<Seq>::Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -215,7 +339,7 @@ namespace meta {
|
|||
* over clever re-use of existing types.
|
||||
*/
|
||||
template<typename TYPES>
|
||||
using Tuple = typename BuildTupleType<TYPES>::Type;
|
||||
using Tuple = BuildTupleType<TYPES>::Type;
|
||||
|
||||
|
||||
using std::tuple_size;
|
||||
|
|
@ -227,14 +351,14 @@ namespace meta {
|
|||
template<typename...TYPES>
|
||||
struct RebindTupleTypes
|
||||
{
|
||||
using Seq = typename Types<TYPES...>::Seq;
|
||||
using List = typename Seq::List;
|
||||
using Seq = Types<TYPES...>::Seq;
|
||||
using List = Seq::List;
|
||||
};
|
||||
template<typename...TYPES>
|
||||
struct RebindTupleTypes<std::tuple<TYPES...>>
|
||||
{
|
||||
using Seq = typename Types<TYPES...>::Seq;
|
||||
using List = typename Seq::List;
|
||||
using Seq = Types<TYPES...>::Seq;
|
||||
using List = Seq::List;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -272,7 +396,7 @@ namespace meta {
|
|||
: Tuple<TYPES>
|
||||
{
|
||||
/** meta-sequence to drive instantiation of the ElmMapper */
|
||||
using SequenceIterator = typename BuildIdxIter<TYPES>::Ascending;
|
||||
using SequenceIterator = BuildIdxIter<TYPES>::Ascending;
|
||||
|
||||
template<size_t idx, class SRC>
|
||||
static auto
|
||||
|
|
@ -312,7 +436,7 @@ namespace meta {
|
|||
|
||||
|
||||
template<class SRC, class TAR, size_t i>
|
||||
using ExtractArg = typename ElementExtractor<SRC, TAR>::template Access<i>;
|
||||
using ExtractArg = ElementExtractor<SRC, TAR>::template Access<i>;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -365,10 +489,10 @@ namespace meta {
|
|||
class BuildTupleAccessor
|
||||
{
|
||||
// prepare recursion...
|
||||
using Head = typename Split<TYPES>::Head;
|
||||
using Tail = typename Split<TYPES>::Tail;
|
||||
using Head = Split<TYPES>::Head;
|
||||
using Tail = Split<TYPES>::Tail;
|
||||
using NextBuilder = BuildTupleAccessor<_X_, Tail,TUP, i+1>;
|
||||
using NextAccessor = typename NextBuilder::Product;
|
||||
using NextAccessor = NextBuilder::Product;
|
||||
public:
|
||||
|
||||
/** type of the product created by this template.
|
||||
|
|
@ -451,7 +575,7 @@ namespace meta {
|
|||
dump (std::tuple<TYPES...> const& tuple)
|
||||
{
|
||||
using BuildAccessor = BuildTupleAccessor<TupleElementDisplayer, Types<TYPES...>>;
|
||||
using Displayer = typename BuildAccessor::Product ;
|
||||
using Displayer = BuildAccessor::Product ;
|
||||
|
||||
return static_cast<Displayer const&> (tuple)
|
||||
.dump();
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ namespace meta {
|
|||
>
|
||||
{ };
|
||||
|
||||
using SupportedSourceTypes = typename Filter<DataValues::List, allow_Conversion>::List;
|
||||
using SupportedSourceTypes = Filter<DataValues::List, allow_Conversion>::List;
|
||||
|
||||
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ namespace meta {
|
|||
struct ElementExtractor<lib::diff::Rec, std::tuple<TYPES...>>
|
||||
{
|
||||
template<size_t i>
|
||||
using TargetType = typename Pick<Types<TYPES...>, i>::Type;
|
||||
using TargetType = Pick<Types<TYPES...>, i>::Type;
|
||||
|
||||
|
||||
template<size_t i>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace meta {
|
|||
template<class TY, class TYPES, size_t i>
|
||||
struct Pick<Node<TY,TYPES>, i>
|
||||
{
|
||||
using Type = typename Pick<TYPES, i-1>::Type;
|
||||
using Type = Pick<TYPES, i-1>::Type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -111,11 +111,11 @@ namespace meta {
|
|||
template< class TY, class TYPES
|
||||
, template<class> class _P_
|
||||
>
|
||||
struct Filter<Node<TY,TYPES>,_P_> { using List = typename CondNode< _P_<TY>::value
|
||||
, TY
|
||||
, typename Filter<TYPES,_P_>::List
|
||||
>::Next
|
||||
; };
|
||||
struct Filter<Node<TY,TYPES>,_P_> { using List = CondNode< _P_<TY>::value
|
||||
, TY
|
||||
, typename Filter<TYPES,_P_>::List
|
||||
>::Next
|
||||
; };
|
||||
|
||||
|
||||
/** append (concatenate) lists-of-types */
|
||||
|
|
@ -157,11 +157,11 @@ namespace meta {
|
|||
using List = Nil; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct PickLast<Node<TY,TYPES>> { using Type = typename PickLast<TYPES>::Type;
|
||||
using List = typename Append< TY
|
||||
, typename PickLast<TYPES>::List
|
||||
>::List
|
||||
; };
|
||||
struct PickLast<Node<TY,TYPES>> { using Type = PickLast<TYPES>::Type;
|
||||
using List = Append< TY
|
||||
, typename PickLast<TYPES>::List
|
||||
>::List
|
||||
; };
|
||||
|
||||
|
||||
|
||||
|
|
@ -203,11 +203,11 @@ namespace meta {
|
|||
|
||||
/** extract prefix of given length */
|
||||
template<class LI, uint l>
|
||||
using Prefix = typename Splice<LI, Nil, l>::Front;
|
||||
using Prefix = Splice<LI, Nil, l>::Front;
|
||||
|
||||
/** extract suffix starting at given pos */
|
||||
template<class LI, uint p>
|
||||
using Suffix = typename Splice<LI, Nil, p>::Back;
|
||||
using Suffix = Splice<LI, Nil, p>::Back;
|
||||
|
||||
|
||||
|
||||
|
|
@ -222,13 +222,13 @@ namespace meta {
|
|||
template<class T, class TYPES>
|
||||
struct Dissect<Node<T,TYPES>>
|
||||
{
|
||||
using List = Node<T,TYPES>; ///< the complete list
|
||||
using Head = T; ///< first element
|
||||
using First = Node<T,Nil>; ///< a list containing the first element
|
||||
using Tail = TYPES; ///< remainder of the list starting with the second elm.
|
||||
using Prefix = typename PickLast<List>::List; ///< all of the list, up to but excluding the last element
|
||||
using End = typename PickLast<List>::Type; ///< the last element
|
||||
using Last = Node<End,Nil>; ///< a list containing the last element
|
||||
using List = Node<T,TYPES>; ///< the complete list
|
||||
using Head = T; ///< first element
|
||||
using First = Node<T,Nil>; ///< a list containing the first element
|
||||
using Tail = TYPES; ///< remainder of the list starting with the second elm.
|
||||
using Prefix = PickLast<List>::List; ///< all of the list, up to but excluding the last element
|
||||
using End = PickLast<List>::Type; ///< the last element
|
||||
using Last = Node<End,Nil>; ///< a list containing the last element
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -276,7 +276,7 @@ namespace meta {
|
|||
* sources, i.e. the Cartesian product.
|
||||
*/
|
||||
template<class TY1,class TY2>
|
||||
struct Distribute { using List = typename PrefixAll<TY1,TY2>::List; };
|
||||
struct Distribute { using List = PrefixAll<TY1,TY2>::List; };
|
||||
|
||||
template<class TY>
|
||||
struct Distribute<Nil,TY> { using List = Nil; };
|
||||
|
|
@ -284,10 +284,10 @@ namespace meta {
|
|||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Distribute<Node<TY,TYPES>,TAIL> { using List = typename Append< typename PrefixAll<TY,TAIL>::List
|
||||
, typename Distribute<TYPES,TAIL>::List
|
||||
>::List
|
||||
; };
|
||||
struct Distribute<Node<TY,TYPES>,TAIL> { using List = Append< typename PrefixAll<TY,TAIL>::List
|
||||
, typename Distribute<TYPES,TAIL>::List
|
||||
>::List
|
||||
; };
|
||||
|
||||
|
||||
|
||||
|
|
@ -306,17 +306,17 @@ namespace meta {
|
|||
*/
|
||||
template< class X
|
||||
, template<class> class _ENUM_>
|
||||
struct Combine { using List = typename Distribute< typename _ENUM_<X>::List
|
||||
, NilNode
|
||||
>::List; };
|
||||
struct Combine { using List = Distribute< typename _ENUM_<X>::List
|
||||
, NilNode
|
||||
>::List; };
|
||||
template< template<class> class _ENUM_>
|
||||
struct Combine<Nil, _ENUM_ > { using List = NilNode; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _ENUM_>
|
||||
struct Combine<Node<TY,TYPES>,_ENUM_> { using List = typename Distribute< typename _ENUM_<TY>::List
|
||||
, typename Combine<TYPES,_ENUM_>::List
|
||||
>::List; };
|
||||
struct Combine<Node<TY,TYPES>,_ENUM_> { using List = Distribute< typename _ENUM_<TY>::List
|
||||
, typename Combine<TYPES,_ENUM_>::List
|
||||
>::List; };
|
||||
|
||||
/** enumeration generator for the Combine metafunction,
|
||||
* yielding an "on" and "off" case; the latter is
|
||||
|
|
@ -334,7 +334,7 @@ namespace meta {
|
|||
template<class FLAGS>
|
||||
struct CombineFlags
|
||||
{
|
||||
using List = typename Combine<FLAGS, FlagOnOff>::List;
|
||||
using List = Combine<FLAGS, FlagOnOff>::List;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ namespace meta {
|
|||
struct Prepend<T, Types<TYPES...>>
|
||||
{
|
||||
using Seq = Types<T, TYPES...>;
|
||||
using List = typename Types<T, TYPES...>::List;
|
||||
using List = Types<T, TYPES...>::List;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -108,9 +108,9 @@ namespace meta {
|
|||
struct Types< Node<H,T> >
|
||||
{
|
||||
using List = Node<H,T>;
|
||||
using Seq = typename Prepend< H
|
||||
, typename Types<T>::Seq
|
||||
>::Seq;
|
||||
using Seq = Prepend< H
|
||||
, typename Types<T>::Seq
|
||||
>::Seq;
|
||||
};
|
||||
template<>
|
||||
struct Types<Nil>
|
||||
|
|
@ -135,7 +135,7 @@ namespace meta {
|
|||
template<typename T1, typename...TS>
|
||||
struct Split<Types<T1,TS...> >
|
||||
{
|
||||
using List = typename Types<T1,TS...>::List;
|
||||
using List = Types<T1,TS...>::List;
|
||||
|
||||
using Head = T1;
|
||||
using First = Types<T1>;
|
||||
|
|
@ -143,11 +143,11 @@ namespace meta {
|
|||
|
||||
// for finding the end we need the help of typelist-util.hpp
|
||||
|
||||
using PrefixList = typename PickLast<List>::List;
|
||||
using TailList = typename Tail::List;
|
||||
using PrefixList = PickLast<List>::List;
|
||||
using TailList = Tail::List;
|
||||
|
||||
using Prefix = typename Types<PrefixList>::Seq;
|
||||
using End = typename PickLast<List>::Type;
|
||||
using Prefix = Types<PrefixList>::Seq;
|
||||
using End = PickLast<List>::Type;
|
||||
using Last = Types<End>;
|
||||
};
|
||||
|
||||
|
|
@ -180,17 +180,17 @@ namespace meta {
|
|||
template<class TYPES, uint i=1>
|
||||
class Shifted
|
||||
{
|
||||
using Tail = typename Split<TYPES>::Tail;
|
||||
using Tail = Split<TYPES>::Tail;
|
||||
public:
|
||||
using Type = typename Shifted<Tail,i-1>::Type;
|
||||
using Head = typename Split<Type>::Head;
|
||||
using Type = Shifted<Tail,i-1>::Type;
|
||||
using Head = Split<Type>::Head;
|
||||
};
|
||||
|
||||
template<class TYPES>
|
||||
struct Shifted<TYPES,0>
|
||||
{
|
||||
using Type = TYPES;
|
||||
using Head = typename Split<Type>::Head; ///< @warning may be Nil in case of an empty list
|
||||
using Head = Split<Type>::Head; ///< @warning may be Nil in case of an empty list
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ namespace meta {
|
|||
template<typename...TYPES, size_t i>
|
||||
struct Pick<Types<TYPES...>, i>
|
||||
{
|
||||
using Type = typename Shifted<Types<TYPES...>, i>::Head;
|
||||
using Type = Shifted<Types<TYPES...>, i>::Head;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -214,8 +214,8 @@ namespace meta {
|
|||
template<typename T, size_t N>
|
||||
struct Repeat
|
||||
{
|
||||
using Rem = typename Repeat<T, N-1>::Seq;
|
||||
using Seq = typename Prepend<T,Rem>::Seq;
|
||||
using Rem = Repeat<T, N-1>::Seq;
|
||||
using Seq = Prepend<T,Rem>::Seq;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -84,10 +84,10 @@ namespace meta {
|
|||
* @see [std::enable_if](http://en.cppreference.com/w/cpp/types/enable_if)
|
||||
*/
|
||||
template <class Cond, class T = void>
|
||||
using enable_if = typename enable_if_c<Cond::value, T>::type;
|
||||
using enable_if = enable_if_c<Cond::value, T>::type;
|
||||
|
||||
template <class Cond, class T = void>
|
||||
using disable_if = typename enable_if_c<not Cond::value, T>::type;
|
||||
using disable_if = enable_if_c<not Cond::value, T>::type;
|
||||
|
||||
|
||||
|
||||
|
|
@ -114,9 +114,9 @@ namespace meta {
|
|||
class _DetectNested_TypeResult
|
||||
{
|
||||
template<class ZZ>
|
||||
static Yes_t check(typename ZZ::type *);
|
||||
static Yes_t check(ZZ::type *);
|
||||
template<class X>
|
||||
static Yes_t check(typename X::Type *);
|
||||
static Yes_t check(X::Type *);
|
||||
template<class>
|
||||
static No_t check(...);
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ namespace meta {
|
|||
}
|
||||
/** helper to extract the first argument from a variadic arg pack, if any */
|
||||
template<typename...XS>
|
||||
using extractFirst_t = typename _ExtractFirst<XS...>::Type;
|
||||
using extractFirst_t = _ExtractFirst<XS...>::Type;
|
||||
|
||||
|
||||
|
||||
|
|
@ -193,33 +193,6 @@ namespace meta {
|
|||
|
||||
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* check for the necessary precondition, not sufficient.
|
||||
* @remark Detecting the possibility of structured binding reliably will be possible with C++23.
|
||||
* Even a partial implementation, covering only `std::tuple_element` is surprisingly
|
||||
* complicated, due to the built-in limit checks. What do do with a `tuple<>`?
|
||||
*/
|
||||
template<class TUP, size_t siz =std::tuple_size<TUP>::value>
|
||||
struct _Probe_TupleProtocol
|
||||
{ };
|
||||
}
|
||||
template<class TUP>
|
||||
using enable_if_TupleProtocol = std::void_t<_Probe_TupleProtocol<std::decay_t<TUP>>>;
|
||||
|
||||
/** Trait template to detect a »tuple-like« type,
|
||||
* which can be used in structured bindings.
|
||||
* @note we check only one precondition: the support for `std::tuple_size`
|
||||
*/
|
||||
template<class X, typename =void>
|
||||
struct is_Structured
|
||||
: std::false_type
|
||||
{ };
|
||||
|
||||
template<class TUP>
|
||||
struct is_Structured<TUP, enable_if_TupleProtocol<TUP>>
|
||||
: std::true_type
|
||||
{ };
|
||||
|
||||
|
||||
/** Trait template for detecting a typelist type.
|
||||
|
|
@ -231,7 +204,7 @@ namespace meta {
|
|||
class is_Typelist
|
||||
{
|
||||
template<class X>
|
||||
static Yes_t check(typename X::List *);
|
||||
static Yes_t check(X::List *);
|
||||
template<class>
|
||||
static No_t check(...);
|
||||
|
||||
|
|
@ -519,7 +492,7 @@ namespace util {
|
|||
inline std::string
|
||||
showSmartPtr (SP const& smPtr, std::string label = "smP")
|
||||
{
|
||||
using TargetType = typename SP::element_type;
|
||||
using TargetType = SP::element_type;
|
||||
|
||||
return smPtr? label+"("+showAdr(smPtr.get()) + ") ↗" + StringConv<TargetType>::invoke(*smPtr)
|
||||
: BOTTOM_INDICATOR + " «" + typeStr(smPtr) + "»";
|
||||
|
|
|
|||
|
|
@ -107,20 +107,20 @@ namespace meta {
|
|||
template<typename TY, typename SEL =void>
|
||||
struct ValueTypeBinding
|
||||
{
|
||||
using value_type = typename RefTraits<TY>::Value;
|
||||
using reference = typename RefTraits<TY>::Reference;
|
||||
using pointer = typename RefTraits<TY>::Pointer;
|
||||
using value_type = RefTraits<TY>::Value;
|
||||
using reference = RefTraits<TY>::Reference;
|
||||
using pointer = RefTraits<TY>::Pointer;
|
||||
};
|
||||
|
||||
/** specialisation for classes providing STL style type binding definitions */
|
||||
template<typename TY>
|
||||
struct ValueTypeBinding<TY, enable_if<use_ValueTypebindings<TY>> >
|
||||
{
|
||||
using _SrcType = typename RefTraits<TY>::Value;
|
||||
using _SrcType = RefTraits<TY>::Value;
|
||||
|
||||
using value_type = typename _SrcType::value_type;
|
||||
using reference = typename _SrcType::reference;
|
||||
using pointer = typename _SrcType::pointer;
|
||||
using value_type = _SrcType::value_type;
|
||||
using reference = _SrcType::reference;
|
||||
using pointer = _SrcType::pointer;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -159,9 +159,9 @@ namespace meta {
|
|||
>;
|
||||
|
||||
using ResType = _ValRef;
|
||||
using value_type = typename RefTraits<ResType>::Value;
|
||||
using reference = typename RefTraits<ResType>::Reference;
|
||||
using pointer = typename RefTraits<ResType>::Pointer;
|
||||
using value_type = RefTraits<ResType>::Value;
|
||||
using reference = RefTraits<ResType>::Reference;
|
||||
using pointer = RefTraits<ResType>::Pointer;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,20 +70,20 @@ namespace meta {
|
|||
template<size_t n>
|
||||
struct BuildIndexSeq
|
||||
{
|
||||
using Ascending = typename BuildIndexSeq<n-1>::Ascending::template AppendElm<n-1>;
|
||||
using Descending = typename BuildIndexSeq<n-1>::Descending::template PrependElm<n-1>;
|
||||
using Ascending = BuildIndexSeq<n-1>::Ascending::template AppendElm<n-1>;
|
||||
using Descending = BuildIndexSeq<n-1>::Descending::template PrependElm<n-1>;
|
||||
|
||||
template<size_t d>
|
||||
using OffsetBy = typename BuildIndexSeq<n-1>::template OffsetBy<d>::template AppendElm<n-1+d>;
|
||||
using OffsetBy = BuildIndexSeq<n-1>::template OffsetBy<d>::template AppendElm<n-1+d>;
|
||||
|
||||
template<size_t x>
|
||||
using FilledWith = typename BuildIndexSeq<n-1>::template FilledWith<x>::template AppendElm<x>;
|
||||
using FilledWith = BuildIndexSeq<n-1>::template FilledWith<x>::template AppendElm<x>;
|
||||
|
||||
template<size_t c>
|
||||
using First = typename BuildIndexSeq<std::min(c,n)>::Ascending;
|
||||
using First = BuildIndexSeq<std::min(c,n)>::Ascending;
|
||||
|
||||
template<size_t c>
|
||||
using After = typename BuildIndexSeq< (n>c)? n-c : 0>::template OffsetBy<c>;
|
||||
using After = BuildIndexSeq< (n>c)? n-c : 0>::template OffsetBy<c>;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -118,20 +118,20 @@ namespace meta {
|
|||
enum {SIZ = sizeof...(TYPES) };
|
||||
using Builder = BuildIndexSeq<SIZ>;
|
||||
|
||||
using Ascending = typename Builder::Ascending;
|
||||
using Descending = typename Builder::Descending;
|
||||
using Ascending = Builder::Ascending;
|
||||
using Descending = Builder::Descending;
|
||||
|
||||
template<size_t d>
|
||||
using OffsetBy = typename Builder::template OffsetBy<d>;
|
||||
using OffsetBy = Builder::template OffsetBy<d>;
|
||||
|
||||
template<size_t x>
|
||||
using FilledWith = typename Builder::template FilledWith<x>;
|
||||
using FilledWith = Builder::template FilledWith<x>;
|
||||
|
||||
template<size_t c>
|
||||
using First = typename Builder::template First<c>;
|
||||
using First = Builder::template First<c>;
|
||||
|
||||
template<size_t c>
|
||||
using After = typename Builder::template After<c>;
|
||||
using After = Builder::template After<c>;
|
||||
};
|
||||
|
||||
/** build an index number sequence from a type sequence */
|
||||
|
|
@ -193,47 +193,16 @@ namespace meta {
|
|||
using Apply = Types<META<TYPES>...>;
|
||||
|
||||
template<template<typename...> class O>
|
||||
using Rebind = typename lib::meta::RebindVariadic<O, Seq>::Type;
|
||||
using Rebind = lib::meta::RebindVariadic<O, Seq>::Type;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using AndAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__and_>;
|
||||
using AndAll = ElmTypes<Apply<PRED>>::template Rebind<std::__and_>;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using OrAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__or_>;
|
||||
using OrAll = ElmTypes<Apply<PRED>>::template Rebind<std::__or_>;
|
||||
};
|
||||
|
||||
/** partial specialisation to handle types
|
||||
* supporting the C++ »tuple protocol«
|
||||
*/
|
||||
template<class TUP>
|
||||
struct ElmTypes<TUP, enable_if_TupleProtocol<TUP>>
|
||||
{
|
||||
template<typename>
|
||||
struct Extract;
|
||||
template<size_t...idx>
|
||||
struct Extract<std::index_sequence<idx...>>
|
||||
{
|
||||
using ElmTypes = Types<typename std::tuple_element<idx,TUP>::type ...>;
|
||||
};
|
||||
|
||||
static constexpr size_t SIZ = std::tuple_size<TUP>::value;
|
||||
|
||||
using Idx = std::make_index_sequence<SIZ>;
|
||||
using Seq = typename Extract<Idx>::ElmTypes;
|
||||
using Tup = typename RebindVariadic<std::tuple, Seq>::Type;
|
||||
|
||||
template<template<class> class META>
|
||||
using Apply = typename ElmTypes<Seq>::template Apply<META>;
|
||||
|
||||
template<template<typename...> class O>
|
||||
using Rebind = typename RebindVariadic<O, Seq>::Type;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using AndAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__and_>;
|
||||
|
||||
template<template<class> class PRED>
|
||||
using OrAll = typename ElmTypes<Apply<PRED>>::template Rebind<std::__or_>;
|
||||
};
|
||||
// Note: a further specialisation for any »tuple-like« is defined in tuple-helper.hpp
|
||||
|
||||
|
||||
|
||||
|
|
@ -244,23 +213,56 @@ namespace meta {
|
|||
|
||||
/** helper to invoke a functor, passing instances of std::integral_constant
|
||||
* @tparam N size of the index-sequence to use for instantiation
|
||||
* @remark the functor is given for...
|
||||
* - to be invoked either (as void) for each index
|
||||
* - or as a predicate, combining the results with AND / OR
|
||||
*/
|
||||
template<size_t N>
|
||||
class WithIdxSeq
|
||||
{
|
||||
template<class FUN, size_t...idx>
|
||||
static void
|
||||
invoke (FUN&& fun, std::index_sequence<idx...>)
|
||||
static constexpr void
|
||||
invoke_forEach (FUN&& fun, std::index_sequence<idx...>)
|
||||
{
|
||||
(fun (std::integral_constant<size_t,idx>{}), ...);
|
||||
}
|
||||
|
||||
template<class FUN, size_t...idx>
|
||||
static constexpr bool
|
||||
and_forEach (FUN&& fun, std::index_sequence<idx...>)
|
||||
{
|
||||
return (fun (std::integral_constant<size_t,idx>{}) and ...);
|
||||
}
|
||||
|
||||
template<class FUN, size_t...idx>
|
||||
static constexpr bool
|
||||
or_forEach (FUN&& fun, std::index_sequence<idx...>)
|
||||
{
|
||||
return (fun (std::integral_constant<size_t,idx>{}) or ...);
|
||||
}
|
||||
|
||||
using IdxSeq = std::make_index_sequence<N>;
|
||||
|
||||
public:
|
||||
template<class FUN>
|
||||
static void
|
||||
static constexpr void
|
||||
invoke (FUN&& fun)
|
||||
{
|
||||
invoke (std::forward<FUN>(fun), std::make_index_sequence<N>{});
|
||||
invoke_forEach (std::forward<FUN>(fun), IdxSeq{});
|
||||
}
|
||||
|
||||
template<class FUN>
|
||||
static constexpr bool
|
||||
andAll (FUN&& fun)
|
||||
{
|
||||
return and_forEach (std::forward<FUN>(fun), IdxSeq{});
|
||||
}
|
||||
|
||||
template<class FUN>
|
||||
static constexpr bool
|
||||
orAny (FUN&& fun)
|
||||
{
|
||||
return or_forEach (std::forward<FUN>(fun), IdxSeq{});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -268,30 +270,31 @@ namespace meta {
|
|||
* Invoke a function (or λ) with index numbers derived from some variadic count.
|
||||
* Notably this construct can be used for compile-time iteration over a structure.
|
||||
* Instances of `std::integral_constant` are passed in sequence to the functor.
|
||||
* The _size_ of the index sequence is derived from the following sources
|
||||
* The _size_ of the index sequence is derived using a \ref ElmTypes specialisation
|
||||
* - if the type \a TTX is _tuple-like,_ then std::tuple_size<TTX> is used
|
||||
* - otherwise, if the type is a loki-style type sequence or type list,
|
||||
* the number of type nodes is used
|
||||
* - otherwise, as fall-back the number of template parameters is used
|
||||
* - otherwise, if the type is a _type sequence_ (`Types<T...>`), then
|
||||
* the size of this meta sequence is used
|
||||
* - otherwise, sequence-size ≡ 1 is used as fall-back
|
||||
*/
|
||||
template<class TTX, class FUN>
|
||||
inline void
|
||||
forEachIDX (FUN&& fun)
|
||||
{
|
||||
auto N = []{
|
||||
if constexpr (is_Structured<TTX>())
|
||||
return size_t(std::tuple_size<TTX>::value);
|
||||
else
|
||||
if constexpr (lib::meta::is_Typelist<TTX>::value)
|
||||
return lib::meta::count<typename TTX::List>();
|
||||
else
|
||||
{ // Fallback: rebind template arguments into a type sequence
|
||||
using Seq = typename RebindVariadic<Types, TTX>::Type;
|
||||
return size_t(count<Seq>());
|
||||
}
|
||||
};
|
||||
|
||||
WithIdxSeq<N()>::invoke (std::forward<FUN> (fun));
|
||||
WithIdxSeq<ElmTypes<TTX>::SIZ>::invoke (std::forward<FUN> (fun));
|
||||
}
|
||||
|
||||
template<class TTX, class FUN>
|
||||
inline bool
|
||||
andAllIDX (FUN&& fun)
|
||||
{
|
||||
return WithIdxSeq<ElmTypes<TTX>::SIZ>::andAll (std::forward<FUN> (fun));
|
||||
}
|
||||
|
||||
template<class TTX, class FUN>
|
||||
inline bool
|
||||
orAnyIDX (FUN&& fun)
|
||||
{
|
||||
return WithIdxSeq<ElmTypes<TTX>::SIZ>::orAny (std::forward<FUN> (fun));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@
|
|||
** template<typename...CASES>
|
||||
** struct MyModel
|
||||
** {
|
||||
** using SubSeq = typename _Vari<MyModel, CASES...>::Prefix;
|
||||
** using SubSeq = _Vari<MyModel, CASES...>::Prefix;
|
||||
**
|
||||
** // adapt a predecessor sequence
|
||||
** MyModel (SubSeq&& subModel);
|
||||
**
|
||||
**
|
||||
** using Tuple = typename RebindVariadic<std::tuple, CASES...>::Type;
|
||||
** using Tuple = RebindVariadic<std::tuple, CASES...>::Type;
|
||||
** }
|
||||
** \endcode
|
||||
** @see param-weaving-pattern.hpp "usage example"
|
||||
|
|
@ -138,15 +138,15 @@ namespace meta {
|
|||
template<template<class...> class L, typename X, typename...XS>
|
||||
struct _Vari<L, X,XS...>
|
||||
{
|
||||
using Penult = typename _Vari<L,XS...>::Penult;
|
||||
using Ultima = typename _Vari<L,XS...>::Ultima;
|
||||
using Penult = _Vari<L,XS...>::Penult;
|
||||
using Ultima = _Vari<L,XS...>::Ultima;
|
||||
|
||||
using _Tail_Pre_ = typename _Vari<L,XS...>::Prefix;
|
||||
using _Tail_Rev_ = typename _Vari<L,XS...>::Revers;
|
||||
using _Tail_Pre_ = _Vari<L,XS...>::Prefix;
|
||||
using _Tail_Rev_ = _Vari<L,XS...>::Revers;
|
||||
|
||||
using Remain = L<XS...>;
|
||||
using Prefix = typename _Vari<L, X, _Tail_Pre_>::Prepend;
|
||||
using Revers = typename _Vari<L, Ultima, _Tail_Rev_>::Prepend;
|
||||
using Prefix = _Vari<L, X, _Tail_Pre_>::Prepend;
|
||||
using Revers = _Vari<L, Ultima, _Tail_Rev_>::Prepend;
|
||||
};
|
||||
|
||||
}} // namespace lib::meta
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ namespace lib {
|
|||
template<typename RAW>
|
||||
struct BuildRefcountPtr
|
||||
{
|
||||
using RawType = typename std::remove_pointer<RAW>::type;
|
||||
using RawType = std::remove_pointer<RAW>::type;
|
||||
using BareType = RawType *;
|
||||
using ResultType = std::shared_ptr<RawType>;
|
||||
|
||||
|
|
@ -210,8 +210,8 @@ namespace lib {
|
|||
struct FabConfig
|
||||
{
|
||||
using WrapFunctor = Wrapper<TY>;
|
||||
using BareProduct = typename WrapFunctor::BareType;
|
||||
using WrappedProduct = typename WrapFunctor::ResultType;
|
||||
using BareProduct = WrapFunctor::BareType;
|
||||
using WrappedProduct = WrapFunctor::ResultType;
|
||||
|
||||
typedef BareProduct SIG_Fab(void);
|
||||
|
||||
|
|
@ -228,8 +228,8 @@ namespace lib {
|
|||
struct FabConfig<RET(ARGS...), Wrapper>
|
||||
{
|
||||
using WrapFunctor = Wrapper<RET>;
|
||||
using BareProduct = typename WrapFunctor::BareType;
|
||||
using WrappedProduct = typename WrapFunctor::ResultType;
|
||||
using BareProduct = WrapFunctor::BareType;
|
||||
using WrappedProduct = WrapFunctor::ResultType;
|
||||
|
||||
typedef BareProduct SIG_Fab(ARGS...);
|
||||
|
||||
|
|
@ -259,14 +259,14 @@ namespace lib {
|
|||
: public FabConfig<SIG,Wrapper>::WrapFunctor
|
||||
{
|
||||
using _Conf = FabConfig<SIG,Wrapper>;
|
||||
using SIG_Fab = typename _Conf::SIG_Fab;
|
||||
using SIG_Fab = _Conf::SIG_Fab;
|
||||
using _Fab = Fab<SIG_Fab,ID>;
|
||||
|
||||
_Fab funcTable_;
|
||||
|
||||
|
||||
protected:
|
||||
using Creator = typename _Fab::FactoryFunc;
|
||||
using Creator = _Fab::FactoryFunc;
|
||||
|
||||
Creator&
|
||||
selectProducer (ID const& id)
|
||||
|
|
@ -276,7 +276,7 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
using Product = typename _Conf::WrappedProduct;
|
||||
using Product = _Conf::WrappedProduct;
|
||||
|
||||
/**
|
||||
* Core operation of the factory:
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ namespace lib {
|
|||
>
|
||||
class InPlaceAnyHolder
|
||||
{
|
||||
using BaseP = typename AccessPolicy::Base *;
|
||||
using BaseP = AccessPolicy::Base *;
|
||||
|
||||
/** Inner capsule managing the contained object (interface) */
|
||||
struct Buffer
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ namespace util {
|
|||
using PFun = FUN;
|
||||
PFun parse;
|
||||
|
||||
using Result = typename _Fun<PFun>::Ret::Result;
|
||||
using Result = _Fun<PFun>::Ret::Result;
|
||||
|
||||
Connex (FUN pFun)
|
||||
: parse{pFun}
|
||||
|
|
@ -281,7 +281,7 @@ namespace util {
|
|||
inline auto
|
||||
buildConnex (Syntax<PAR> const& anchor)
|
||||
{
|
||||
using Con = typename Syntax<PAR>::Connex;
|
||||
using Con = Syntax<PAR>::Connex;
|
||||
return Con{anchor};
|
||||
}
|
||||
|
||||
|
|
@ -336,9 +336,9 @@ namespace util {
|
|||
inline auto
|
||||
adaptConnex (CON&& connex, BIND&& modelBinding)
|
||||
{
|
||||
using RX = typename CON::Result;
|
||||
using RX = CON::Result;
|
||||
using Arg = std::add_rvalue_reference_t<RX>;
|
||||
using AdaptedRes = typename _ProbeFunReturn<Arg,BIND>::Ret;
|
||||
using AdaptedRes = _ProbeFunReturn<Arg,BIND>::Ret;
|
||||
return Connex{[origConnex = forward<CON>(connex)
|
||||
,binding = forward<BIND>(modelBinding)
|
||||
]
|
||||
|
|
@ -357,7 +357,7 @@ namespace util {
|
|||
inline auto
|
||||
toStringConnex (CON&& connex, uint part)
|
||||
{
|
||||
using Result = typename CON::Result;
|
||||
using Result = CON::Result;
|
||||
return Connex([baseConnex = forward<CON>(connex)
|
||||
,part
|
||||
]
|
||||
|
|
@ -442,9 +442,9 @@ namespace util {
|
|||
|
||||
/* === Builder functions to mark which side of the combinator to pick === */
|
||||
|
||||
using SubSeq = typename _Vari<AltModel, CASES...>::Prefix; ///< a nested sub-model to extend
|
||||
using Penult = typename _Vari<AltModel, CASES...>::Penult; ///< plain value expected for left-branch
|
||||
using Ultima = typename _Vari<AltModel, CASES...>::Ultima; ///< plain value expected for right-branch
|
||||
using SubSeq = _Vari<AltModel, CASES...>::Prefix; ///< a nested sub-model to extend
|
||||
using Penult = _Vari<AltModel, CASES...>::Penult; ///< plain value expected for left-branch
|
||||
using Ultima = _Vari<AltModel, CASES...>::Ultima; ///< plain value expected for right-branch
|
||||
|
||||
static AltModel
|
||||
mark_left (SubSeq&& leftCases)
|
||||
|
|
@ -524,9 +524,9 @@ namespace util {
|
|||
inline auto
|
||||
sequenceConnex (C1&& connex1, C2&& connex2)
|
||||
{
|
||||
using R1 = typename decay_t<C1>::Result;
|
||||
using R2 = typename decay_t<C2>::Result;
|
||||
using ProductResult = typename _Join<SeqModel, R1, R2>::Result;
|
||||
using R1 = decay_t<C1>::Result;
|
||||
using R2 = decay_t<C2>::Result;
|
||||
using ProductResult = _Join<SeqModel, R1, R2>::Result;
|
||||
using ProductEval = Eval<ProductResult>;
|
||||
return Connex{[conL = forward<C1>(connex1)
|
||||
,conR = forward<C2>(connex2)
|
||||
|
|
@ -558,9 +558,9 @@ namespace util {
|
|||
inline auto
|
||||
branchedConnex (C1&& connex1, C2&& connex2)
|
||||
{
|
||||
using R1 = typename decay_t<C1>::Result;
|
||||
using R2 = typename decay_t<C2>::Result;
|
||||
using SumResult = typename _Join<AltModel, R1, R2>::Result;
|
||||
using R1 = decay_t<C1>::Result;
|
||||
using R2 = decay_t<C2>::Result;
|
||||
using SumResult = _Join<AltModel, R1, R2>::Result;
|
||||
using SumEval = Eval<SumResult>;
|
||||
return Connex{[conL = forward<C1>(connex1)
|
||||
,conR = forward<C2>(connex2)
|
||||
|
|
@ -595,7 +595,7 @@ namespace util {
|
|||
,C1&& delimConnex
|
||||
,C2&& bodyConnex)
|
||||
{
|
||||
using Res = typename decay_t<C2>::Result;
|
||||
using Res = decay_t<C2>::Result;
|
||||
using IterResult = IterModel<Res>;
|
||||
using IterEval = Eval<IterResult>;
|
||||
return Connex{[sep = forward<C1>(delimConnex)
|
||||
|
|
@ -636,7 +636,7 @@ namespace util {
|
|||
inline auto
|
||||
optionalConnex (CNX&& connex)
|
||||
{
|
||||
using Res = typename decay_t<CNX>::Result;
|
||||
using Res = decay_t<CNX>::Result;
|
||||
using OptResult = optional<Res>;
|
||||
using OptEval = Eval<OptResult>;
|
||||
return Connex{[body = forward<CNX>(connex)
|
||||
|
|
@ -661,7 +661,7 @@ namespace util {
|
|||
,C3&& bodyConnex
|
||||
,bool isOptional)
|
||||
{
|
||||
using Res = typename decay_t<C3>::Result;
|
||||
using Res = decay_t<C3>::Result;
|
||||
return Connex{[opening = forward<C1>(openingConnex)
|
||||
,closing = forward<C2>(closingConnex)
|
||||
,body = forward<C3>(bodyConnex)
|
||||
|
|
@ -704,12 +704,12 @@ namespace util {
|
|||
class Parser
|
||||
: public CON
|
||||
{
|
||||
using PFun = typename CON::PFun;
|
||||
using PFun = CON::PFun;
|
||||
static_assert (_Fun<PFun>(), "Connex must define a parse-function");
|
||||
|
||||
public:
|
||||
using Connex = CON;
|
||||
using Result = typename CON::Result;
|
||||
using Result = CON::Result;
|
||||
|
||||
static_assert (has_Sig<PFun, Eval<Result>(StrView)>()
|
||||
,"Signature of the parse-function not suitable");
|
||||
|
|
@ -785,8 +785,8 @@ namespace util {
|
|||
PAR parse_;
|
||||
|
||||
public:
|
||||
using Connex = typename PAR::Connex;
|
||||
using Result = typename PAR::Result;
|
||||
using Connex = PAR::Connex;
|
||||
using Result = PAR::Result;
|
||||
|
||||
Syntax()
|
||||
: parse_{Nil()}
|
||||
|
|
@ -826,7 +826,7 @@ namespace util {
|
|||
Syntax&
|
||||
operator= (Syntax<PX> refSyntax)
|
||||
{
|
||||
using ConX = typename PX::Connex;
|
||||
using ConX = PX::Connex;
|
||||
ConX& refConnex = refSyntax;
|
||||
parse_.parse = move(refConnex.parse);
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -226,7 +226,6 @@ namespace lib {
|
|||
{
|
||||
static_assert (0 < chunk_size, "PathArray chunk_size must be nonempty");
|
||||
|
||||
using CcP = const char*;
|
||||
using LiteralArray = std::array<Literal, chunk_size>;
|
||||
|
||||
LiteralArray elms_;
|
||||
|
|
@ -245,8 +244,8 @@ namespace lib {
|
|||
PathArray (IndexSeq<prefix...>
|
||||
,IndexSeq<rest...>
|
||||
,ARGS&& ...args)
|
||||
: elms_{pickInit<prefix,CcP> (forward<ARGS>(args)...) ...}
|
||||
, tail_{pickArg<rest> (forward<ARGS>(args)...) ...}
|
||||
: elms_{pickInit<prefix, CStr> (forward<ARGS>(args)...) ...}
|
||||
, tail_{pickArg<rest> (forward<ARGS>(args)...) ...}
|
||||
{
|
||||
this->normalise();
|
||||
}
|
||||
|
|
@ -260,8 +259,8 @@ namespace lib {
|
|||
template<typename...ARGS>
|
||||
struct Split
|
||||
{
|
||||
using Prefix = typename meta::BuildIndexSeq<chunk_size>::Ascending;
|
||||
using Rest = typename meta::BuildIdxIter<ARGS...>::template After<chunk_size>;
|
||||
using Prefix = meta::BuildIndexSeq<chunk_size>::Ascending;
|
||||
using Rest = meta::BuildIdxIter<ARGS...>::template After<chunk_size>;
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
@ -492,7 +491,7 @@ namespace lib {
|
|||
normalise()
|
||||
{
|
||||
if (size() == 0) return;
|
||||
const char* fill = Symbol::EMPTY;
|
||||
CStr fill = Symbol::EMPTY;
|
||||
|
||||
Literal* end = elms_.end();
|
||||
Literal* pos = elms_.begin();
|
||||
|
|
@ -561,8 +560,8 @@ namespace lib {
|
|||
{
|
||||
if (l.size() != r.size()) return false;
|
||||
|
||||
typename PathArray<cl>::iterator lp = l.begin();
|
||||
typename PathArray<cl>::iterator rp = r.begin();
|
||||
auto lp = l.begin();
|
||||
auto rp = r.begin();
|
||||
while (lp and rp)
|
||||
{
|
||||
if (*lp != *rp) return false;
|
||||
|
|
|
|||
|
|
@ -366,8 +366,8 @@ namespace lib {
|
|||
{
|
||||
private:
|
||||
typedef polyvalue::Trait<CPY> _Traits;
|
||||
typedef typename _Traits::CopyAPI _CopyHandlingAdapter;
|
||||
typedef typename _Traits::Assignment _AssignmentPolicy; /////////////////TICKET #1197 : confusingly indirect decision logic
|
||||
typedef _Traits::CopyAPI _CopyHandlingAdapter;
|
||||
typedef _Traits::Assignment _AssignmentPolicy; /////////////////TICKET #1197 : confusingly indirect decision logic
|
||||
enum{
|
||||
siz = storage + _Traits::ADMIN_OVERHEAD
|
||||
};
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ namespace lib {
|
|||
return definition_;
|
||||
}
|
||||
|
||||
auto operator<=> (QueryText const&) const =default;
|
||||
|
||||
bool
|
||||
empty() const
|
||||
|
|
@ -105,19 +106,6 @@ namespace lib {
|
|||
|
||||
private:
|
||||
string normalise (string const& rawDefinition);
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (QueryText const& q1, QueryText const& q2)
|
||||
{
|
||||
return q1.definition_ == q2.definition_;
|
||||
}
|
||||
friend bool
|
||||
operator< (QueryText const& q1, QueryText const& q2)
|
||||
{
|
||||
return q1.definition_ < q2.definition_;
|
||||
}
|
||||
|
||||
friend HashVal hash_value (QueryText const& entry);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -175,11 +175,11 @@ namespace lib {
|
|||
: public LazyInit<POL>
|
||||
{
|
||||
using Lazy = LazyInit<POL>;
|
||||
using Disabled = typename Lazy::MarkDisabled;
|
||||
using Disabled = Lazy::MarkDisabled;
|
||||
|
||||
using Sig = typename _Fun<POL>::Sig;
|
||||
using Fun = function<Sig>;
|
||||
using Tar = typename _Fun<POL>::Ret;
|
||||
using Sig = _Fun<POL>::Sig;
|
||||
using Fun = function<Sig>;
|
||||
using Tar = _Fun<POL>::Ret;
|
||||
|
||||
Tar maxResult_{Tar::maxVal()}; ///< maximum result val actually to produce < max
|
||||
Tar minResult_{Tar::minVal()}; ///< minimum result val actually to produce > min
|
||||
|
|
@ -363,16 +363,16 @@ namespace lib {
|
|||
using _Fun = lib::meta::_Fun<FUN>;
|
||||
static_assert (_Fun(), "Need something function-like.");
|
||||
|
||||
using Sig = typename _Fun::Sig;
|
||||
using Args = typename _Fun::Args;
|
||||
using BaseIn = typename lib::meta::_Fun<POL>::Args;
|
||||
using Sig = _Fun::Sig;
|
||||
using Args = _Fun::Args;
|
||||
using BaseIn = lib::meta::_Fun<POL>::Args;
|
||||
|
||||
if constexpr (std::is_same_v<Args, BaseIn>)
|
||||
// function accepts same arguments as this RandomDraw
|
||||
return forward<FUN> (fun); // pass-through directly
|
||||
else
|
||||
{// attempt to find a custom adaptor via Policy template
|
||||
using Adaptor = typename POL::template Adaptor<Sig>;
|
||||
using Adaptor = POL::template Adaptor<Sig>;
|
||||
return Adaptor::build (forward<FUN> (fun));
|
||||
}
|
||||
}
|
||||
|
|
@ -392,7 +392,7 @@ namespace lib {
|
|||
{
|
||||
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
|
||||
|
||||
using Res = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using Res = lib::meta::_Fun<FUN>::Ret;
|
||||
using lib::meta::func::chained;
|
||||
using lib::meta::_FunRet;
|
||||
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ namespace lib {
|
|||
public:
|
||||
using GEN::GEN;
|
||||
|
||||
typename GEN::result_type
|
||||
GEN::result_type
|
||||
operator()()
|
||||
{
|
||||
if constexpr (GEN::max() < std::numeric_limits<typename GEN::result_type>::max())
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
** this kind of API design however is anything than trivial, given that
|
||||
** any value can be thrown as exception in C++
|
||||
** @see vault::ThreadJoinable usage example
|
||||
** @see Result_test
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -40,7 +41,6 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/item-wrapper.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
#include "lib/null-value.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <exception>
|
||||
|
|
@ -51,43 +51,13 @@
|
|||
namespace lib {
|
||||
|
||||
namespace error = lumiera::error;
|
||||
|
||||
/**
|
||||
* Helper to invoke an arbitrary callable in a failsafe way.
|
||||
* @param capturedFailure *reference* to a std::exeption_ptr served by side-effect
|
||||
* @param callable anything std::invoke can handle
|
||||
* @return _if_ the invokable has a return type, the result is returned,
|
||||
* _otherwise_ this is a void function
|
||||
* @todo with C++20 the body of the implementation can be replaced by std::invoke_r //////////////////////TICKET #1245
|
||||
*/
|
||||
template<class FUN, typename...ARGS>
|
||||
inline auto
|
||||
failsafeInvoke (std::exception_ptr& capturedFailure
|
||||
,FUN&& callable
|
||||
,ARGS&& ...args) noexcept
|
||||
{
|
||||
using Res = std::invoke_result_t<FUN,ARGS...>;
|
||||
try {
|
||||
capturedFailure = nullptr;
|
||||
if constexpr (std::is_void_v<Res>)
|
||||
std::invoke (std::forward<FUN>(callable), std::forward<ARGS>(args)...);
|
||||
else
|
||||
return std::invoke (std::forward<FUN>(callable), std::forward<ARGS>(args)...);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
capturedFailure = std::current_exception();
|
||||
if constexpr (not std::is_void_v<Res>)
|
||||
return lib::NullValue<Res>::get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Representation of the result of some operation, _EITHER_ a value or a failure.
|
||||
* It can be created for passing a result produced by the operation, or the failure
|
||||
* to do so. The value can be retrieved by implicit or explicit conversion.
|
||||
* @tparam RES the nominal result type to be captured from the function invocation.
|
||||
* @throw error::State on any attempt to access the value in case of failure
|
||||
* @warning this class has a lot of implicit conversions;
|
||||
* care should be taken when defining functions
|
||||
|
|
@ -123,9 +93,16 @@ namespace lib {
|
|||
Result (FUN&& callable, ARGS&& ...args) noexcept
|
||||
: failure_{}
|
||||
{
|
||||
failsafeInvoke (failure_
|
||||
,std::forward<FUN> (callable)
|
||||
,std::forward<ARGS>(args)...);
|
||||
try {
|
||||
static_assert (std::is_invocable_v<FUN,ARGS...>);
|
||||
std::invoke (std::forward<FUN>(callable)
|
||||
,std::forward<ARGS>(args)...
|
||||
);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
failure_ = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
explicit
|
||||
|
|
@ -173,10 +150,19 @@ namespace lib {
|
|||
template<class FUN, typename...ARGS, typename=lib::meta::enable_if<std::is_invocable<FUN,ARGS...>>>
|
||||
Result (FUN&& callable, ARGS&& ...args) noexcept
|
||||
: Result<void>{true}
|
||||
, value_{failsafeInvoke (failure_
|
||||
,std::forward<FUN> (callable)
|
||||
,std::forward<ARGS>(args)...)}
|
||||
{ }
|
||||
, value_{}
|
||||
{
|
||||
try {
|
||||
static_assert (std::is_invocable_r_v<RES,FUN,ARGS...>);
|
||||
value_ = std::invoke_r<RES> (std::forward<FUN>(callable)
|
||||
,std::forward<ARGS>(args)...
|
||||
);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
failure_ = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
// is or is not copyable depending on RES
|
||||
|
||||
|
|
@ -220,7 +206,7 @@ namespace lib {
|
|||
/** deduction guide: find out about result value to capture from a generic callable. */
|
||||
template<typename FUN, typename...ARGS>
|
||||
Result (FUN&&, ARGS&&...) -> Result<std::invoke_result_t<FUN,ARGS...>>;
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace lib
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ namespace lib {
|
|||
{
|
||||
public:
|
||||
void
|
||||
operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
|
||||
operator() (ScopedCollection<I,siz>::ElementHolder& storage)
|
||||
{
|
||||
storage.template create<I>();
|
||||
}
|
||||
|
|
@ -440,7 +440,7 @@ namespace lib {
|
|||
{
|
||||
public:
|
||||
void
|
||||
operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
|
||||
operator() (ScopedCollection<I,siz>::ElementHolder& storage)
|
||||
{
|
||||
storage.template create<TY>();
|
||||
}
|
||||
|
|
@ -461,7 +461,7 @@ namespace lib {
|
|||
{
|
||||
IT iter_;
|
||||
|
||||
using ElementType = typename meta::ValueTypeBinding<IT>::value_type;
|
||||
using ElementType = meta::ValueTypeBinding<IT>::value_type;
|
||||
|
||||
public:
|
||||
PullFrom (IT source)
|
||||
|
|
@ -469,7 +469,7 @@ namespace lib {
|
|||
{ }
|
||||
|
||||
void
|
||||
operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
|
||||
operator() (ScopedCollection<I,siz>::ElementHolder& storage)
|
||||
{
|
||||
storage.template create<ElementType> (*iter_);
|
||||
++iter_;
|
||||
|
|
|
|||
|
|
@ -68,13 +68,13 @@ namespace lib {
|
|||
: util::MoveAssign
|
||||
{
|
||||
using _Vec = std::vector<T*>;
|
||||
using VIter = typename _Vec::iterator;
|
||||
using VIter = _Vec::iterator;
|
||||
|
||||
using RIter = RangeIter<VIter>;
|
||||
using IterType = PtrDerefIter<RIter>;
|
||||
|
||||
using ConstIterType = typename IterType::ConstIterType;
|
||||
using RcIter = typename IterType::WrappedConstIterType;
|
||||
using ConstIterType = IterType::ConstIterType;
|
||||
using RcIter = IterType::WrappedConstIterType;
|
||||
|
||||
_Vec vec_;
|
||||
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ namespace lib {
|
|||
using Bucket = ArrayBucket<I>;
|
||||
|
||||
template<typename X>
|
||||
using XAlloT = typename AlloT::template rebind_traits<std::remove_cv_t<X>>;
|
||||
using XAlloT = AlloT::template rebind_traits<std::remove_cv_t<X>>;
|
||||
|
||||
Allo& baseAllocator() { return *this; }
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ namespace lib {
|
|||
auto
|
||||
adaptAllocator()
|
||||
{
|
||||
using XAllo = typename XAlloT<X>::allocator_type;
|
||||
using XAllo = XAlloT<X>::allocator_type;
|
||||
if constexpr (std::is_constructible_v<XAllo, Allo>)
|
||||
return XAllo{baseAllocator()};
|
||||
else
|
||||
|
|
@ -401,7 +401,7 @@ namespace lib {
|
|||
using Policy = POL<I,E>;
|
||||
|
||||
using Bucket = several::ArrayBucket<I>;
|
||||
using Deleter = typename Bucket::Deleter;
|
||||
using Deleter = Bucket::Deleter;
|
||||
|
||||
public:
|
||||
SeveralBuilder() = default;
|
||||
|
|
@ -477,7 +477,7 @@ namespace lib {
|
|||
SeveralBuilder&&
|
||||
appendAll (std::initializer_list<X> ili)
|
||||
{
|
||||
using Val = typename meta::Strip<X>::TypeReferred;
|
||||
using Val = meta::Strip<X>::TypeReferred;
|
||||
for (Val const& x : ili)
|
||||
emplaceNewElm<Val> (x);
|
||||
return move(*this);
|
||||
|
|
@ -507,7 +507,7 @@ namespace lib {
|
|||
SeveralBuilder&&
|
||||
emplace (ARGS&& ...args)
|
||||
{
|
||||
using Val = typename meta::Strip<TY>::TypeReferred;
|
||||
using Val = meta::Strip<TY>::TypeReferred;
|
||||
emplaceNewElm<Val> (forward<ARGS> (args)...);
|
||||
return move(*this);
|
||||
}
|
||||
|
|
@ -549,7 +549,7 @@ namespace lib {
|
|||
void
|
||||
emplaceCopy (IT& dataSrc)
|
||||
{
|
||||
using Val = typename IT::value_type;
|
||||
using Val = IT::value_type;
|
||||
emplaceNewElm<Val> (*dataSrc);
|
||||
}
|
||||
|
||||
|
|
@ -557,7 +557,7 @@ namespace lib {
|
|||
void
|
||||
emplaceMove (IT& dataSrc)
|
||||
{
|
||||
using Val = typename IT::value_type;
|
||||
using Val = IT::value_type;
|
||||
emplaceNewElm<Val> (move (*dataSrc));
|
||||
}
|
||||
|
||||
|
|
@ -737,9 +737,9 @@ namespace lib {
|
|||
Deleter
|
||||
selectDestructor()
|
||||
{
|
||||
using IVal = typename lib::meta::Strip<I>::TypeReferred;
|
||||
using EVal = typename lib::meta::Strip<E>::TypeReferred;
|
||||
using TVal = typename lib::meta::Strip<TY>::TypeReferred;
|
||||
using IVal = lib::meta::Strip<I>::TypeReferred;
|
||||
using EVal = lib::meta::Strip<E>::TypeReferred;
|
||||
using TVal = lib::meta::Strip<TY>::TypeReferred;
|
||||
|
||||
typename Policy::Fac& factory(*this);
|
||||
|
||||
|
|
@ -783,8 +783,8 @@ namespace lib {
|
|||
void
|
||||
probeMoveCapability()
|
||||
{
|
||||
using TVal = typename lib::meta::Strip<TY>::TypeReferred;
|
||||
using EVal = typename lib::meta::Strip<E>::TypeReferred;
|
||||
using TVal = lib::meta::Strip<TY>::TypeReferred;
|
||||
using EVal = lib::meta::Strip<E>::TypeReferred;
|
||||
|
||||
if (not (is_same_v<TVal,EVal> or is_trivially_copyable_v<TVal>))
|
||||
lock_move = true;
|
||||
|
|
@ -793,7 +793,7 @@ namespace lib {
|
|||
bool
|
||||
canWildMove()
|
||||
{
|
||||
using EVal = typename lib::meta::Strip<E>::TypeReferred;
|
||||
using EVal = lib::meta::Strip<E>::TypeReferred;
|
||||
return is_trivially_copyable_v<EVal> and not lock_move;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,8 +227,8 @@ namespace lib {
|
|||
friend auto begin (Several const& svl) { return svl.begin();}
|
||||
friend auto end (Several const& svl) { return svl.end(); }
|
||||
|
||||
using value_type = typename meta::RefTraits<I>::Value;
|
||||
using reference = typename meta::RefTraits<I>::Reference;
|
||||
using value_type = meta::RefTraits<I>::Value;
|
||||
using reference = meta::RefTraits<I>::Reference;
|
||||
using const_reference = value_type const&;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ namespace stat{
|
|||
% csv.getParsedFieldCnt() % columnCnt % line};
|
||||
}
|
||||
|
||||
using Value = typename std::remove_reference<decltype(col)>::type::ValueType;
|
||||
using Value = std::remove_reference<decltype(col)>::type::ValueType;
|
||||
col.get() = parseAs<Value>(*csv);
|
||||
++csv;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Symbol(impl) - helpers for working with literal string IDs
|
||||
|
||||
Copyright (C)
|
||||
2009, Hermann Vosseler <Ichthyostega@web.de>
|
||||
2009,2017 Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
|
@ -12,15 +12,10 @@
|
|||
* *****************************************************************/
|
||||
|
||||
/** @file symbol-impl.cpp
|
||||
** Collection of helpers for working with the lib::Symbol.
|
||||
**
|
||||
** @todo currently as of 9/09 this is more of a placeholder.
|
||||
** And maybe a location for collecting small bits of implementation,
|
||||
** which could be usable later for real Symbol and Literal datatypes.
|
||||
**
|
||||
** lib::Symbol
|
||||
** control::CommandRegistry for usage example of the hash function.
|
||||
**
|
||||
** Implementation functionality to support definition of lib::Symbol.
|
||||
** @see lib::Symbol
|
||||
** @see control::CommandRegistry for usage example of the hash function.
|
||||
** @see symbol-table.hpp for the implementation of _interned strings_
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -45,7 +40,6 @@ namespace lib {
|
|||
|
||||
const size_t STRING_MAX_RELEVANT = LUMIERA_IDSTRING_MAX_RELEVANT;
|
||||
|
||||
|
||||
namespace { // global symbol table
|
||||
|
||||
SymbolTable&
|
||||
|
|
@ -54,12 +48,6 @@ namespace lib {
|
|||
static SymbolTable theSymbolTable;
|
||||
return theSymbolTable; // Meyer's Singleton
|
||||
}
|
||||
|
||||
inline int
|
||||
strNcmp (CStr a, CStr b, size_t len)
|
||||
{
|
||||
return a == b ? 0 : std::strncmp (a?a:"", b?b:"", len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -87,14 +75,6 @@ namespace lib {
|
|||
|
||||
|
||||
|
||||
/** equality on Literal and Symbol values is defined
|
||||
* based on the content, not the address. */
|
||||
bool
|
||||
Literal::operator== (CStr charPtr) const
|
||||
{
|
||||
return 0 == strNcmp (this->str_, charPtr, STRING_MAX_RELEVANT);
|
||||
}
|
||||
|
||||
|
||||
/** generate hash value based on the Literal's contents.
|
||||
* This function is intended to be picked up by ADL, and should be usable
|
||||
|
|
@ -107,7 +87,7 @@ namespace lib {
|
|||
if (literal)
|
||||
{
|
||||
size_t cnt = 1;
|
||||
const char *pos = literal;
|
||||
CStr pos = literal;
|
||||
for ( ; cnt <= STRING_MAX_RELEVANT and *pos ; ++cnt, ++pos )
|
||||
hash_combine (hash, *pos);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
SYMBOL.hpp - symbolic constant datatype
|
||||
|
||||
Copyright (C)
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
2008,2017 Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
|
@ -16,21 +16,22 @@
|
|||
** Instead of working just with pointers, which could represent pretty much anything,
|
||||
** it is prudent to express the meaning at interfaces and for variables and members explicitly.
|
||||
**
|
||||
** On concept level, while a string is just some sequence of characters and nothing can be said
|
||||
** about mutability or lifetime, a Literal on the contrary is meant to be _static._ It is fixed
|
||||
** and assumed to exist literally as is during the whole lifetime of the execution. The concept
|
||||
** of a Symbol is related, yet slightly different: it is meant to be a distinguishable fixed,
|
||||
** unique token. _Identical sequence_ of characters means we have exactly the _same Symbol._
|
||||
** On conceptual level, while a **string** is just some sequence of characters and nothing can be
|
||||
** said about its mutability or lifetime, a **Literal** is explicitly meant to be _static._ It is
|
||||
** a fixed sequence of characters placed in a stable memory location and assumed to exist during
|
||||
** the whole lifetime of the execution. The concept of a **Symbol** is slightly different: it is
|
||||
** meant to be a distinguishable, fixed, unique token. An _Identical sequence_ of characters means
|
||||
** we have _exactly the same Symbol_.
|
||||
**
|
||||
** These concepts can be fused by treating Symbol as a specialisation of Literal, additionally
|
||||
** maintaining an automatically populated, static [symbol table](\ref symbol-table.hpp), and
|
||||
** we close the circle by allowing Symbol instances to be created from strings at runtime.
|
||||
**
|
||||
** @remark this started on occasion 11/2008, just with a typedef to mark assumption on interfaces
|
||||
** for rules based configuration in the Steam-Layer. Over time, conversions, comparison and
|
||||
** hashcode implementation were added. It turned out that the most smooth integration in
|
||||
** coding practice is achieved when allowing transparent conversion for Literal, but not
|
||||
** for Symbol or std::string.
|
||||
** @remark this abstraction was first used occasionally 11/2008, at that time just as a typedef
|
||||
** to mark assumption on the new interfaces for rules based configuration in the Steam-Layer.
|
||||
** Over time, conversions, comparison and hashcode implementation were added. It turned out
|
||||
** that the most smooth integration in coding practice is achieved when allowing transparent
|
||||
** conversion between Literal ⟷ CStr, but not for Symbol or std::string.
|
||||
** @todo 9/2017 consider this mostly as settled, but might require some finishing touches
|
||||
** - maybe improve interoperation of Symbol and std::string
|
||||
** - investigate performance of the automatic symbol table
|
||||
|
|
@ -64,7 +65,7 @@ cStr (std::string const& rendered)
|
|||
|
||||
namespace lib {
|
||||
|
||||
/** inline string literal
|
||||
/** Inline string literal.
|
||||
* This is a _marker type_ to indicate that
|
||||
* - the string was given literally
|
||||
* - storage is _somewhere_, not managed by Literal,
|
||||
|
|
@ -75,37 +76,38 @@ namespace lib {
|
|||
*/
|
||||
class Literal
|
||||
{
|
||||
CStr str_;
|
||||
|
||||
CStr str_;
|
||||
|
||||
public:
|
||||
/** empty string by default */
|
||||
Literal() noexcept;
|
||||
|
||||
Literal (const char* literal) noexcept
|
||||
: str_(literal)
|
||||
{ }
|
||||
|
||||
Literal (Literal const&) noexcept = default;
|
||||
Literal& operator= (Literal const&) noexcept = default;
|
||||
|
||||
operator CStr() const { return str_; }
|
||||
const char* c() const { return str_; }
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return not str_ or 0 == std::strlen(str_);
|
||||
}
|
||||
|
||||
bool operator== (CStr cString) const;
|
||||
/** empty string by default */
|
||||
constexpr Literal() noexcept;
|
||||
|
||||
constexpr Literal (CStr literal) noexcept
|
||||
: str_(literal)
|
||||
{ }
|
||||
|
||||
constexpr Literal (Literal const&) noexcept = default;
|
||||
constexpr Literal& operator= (Literal const&) noexcept = default;
|
||||
|
||||
constexpr operator CStr() const { return str_; }
|
||||
constexpr const char* c() const { return str_; }
|
||||
|
||||
constexpr bool
|
||||
empty() const
|
||||
{
|
||||
return not str_ or 0 == std::strlen(str_);
|
||||
}
|
||||
|
||||
constexpr bool operator== (CStr cString) const;
|
||||
constexpr size_t length() const;
|
||||
|
||||
protected:
|
||||
/** Assignment generally prohibited */
|
||||
Literal& operator= (CStr newStr) noexcept
|
||||
{
|
||||
str_ = newStr;
|
||||
return *this;
|
||||
}
|
||||
/** Assignment generally prohibited */
|
||||
Literal& operator= (CStr newStr) noexcept
|
||||
{
|
||||
str_ = newStr;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -140,31 +142,50 @@ namespace lib {
|
|||
Symbol (Literal const& base, CStr ext)
|
||||
: Symbol{base, std::string(ext)}
|
||||
{ }
|
||||
|
||||
Symbol (Symbol const&) = default;
|
||||
Symbol (Symbol &&) = default;
|
||||
|
||||
Symbol& operator= (Symbol const&) = default;
|
||||
Symbol& operator= (Symbol &&) = default;
|
||||
|
||||
explicit operator bool() const { return not empty(); }
|
||||
bool empty() const { return *this == BOTTOM.c() or *this == EMPTY.c(); }
|
||||
|
||||
size_t
|
||||
length() const
|
||||
{
|
||||
return std::strlen(c());
|
||||
}
|
||||
|
||||
Symbol (Symbol const&) = default;
|
||||
Symbol (Symbol &&) = default;
|
||||
|
||||
Symbol& operator= (Symbol const&) = default;
|
||||
Symbol& operator= (Symbol &&) = default;
|
||||
|
||||
explicit operator bool() const { return not empty(); }
|
||||
bool empty() const { return *this == BOTTOM.c() or *this == EMPTY.c(); }
|
||||
};
|
||||
|
||||
|
||||
/** @note storage guaranteed to exist */
|
||||
constexpr inline Literal::Literal() noexcept : str_(Symbol::EMPTY) { }
|
||||
|
||||
namespace{
|
||||
constexpr inline int
|
||||
strNcmp (CStr a, CStr b, size_t len)
|
||||
{
|
||||
return a == b ? 0 : std::strncmp (a?a:"", b?b:"", len);
|
||||
}
|
||||
}
|
||||
|
||||
/** safety guard: maximum number of chars to process.
|
||||
* For comparisons, hash calculations etc., when dealing
|
||||
* with raw char ptrs (typically literal values) */
|
||||
extern const size_t STRING_MAX_RELEVANT;
|
||||
|
||||
/** @note storage guaranteed to exist */
|
||||
inline Literal::Literal() noexcept : str_(Symbol::EMPTY) { }
|
||||
/** equality on Literal and Symbol values is defined
|
||||
* based on the content, not the address. */
|
||||
constexpr inline bool
|
||||
Literal::operator== (CStr charPtr) const
|
||||
{
|
||||
return 0 == strNcmp (this->str_, charPtr, STRING_MAX_RELEVANT);
|
||||
}
|
||||
|
||||
constexpr inline size_t
|
||||
Literal::length() const
|
||||
{
|
||||
return std::strlen(c());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ===== to be picked up by ADL ===== */
|
||||
|
|
@ -175,35 +196,16 @@ namespace lib {
|
|||
|
||||
/* === equality comparisons === */
|
||||
|
||||
inline bool operator== (Literal const& s1, Literal const& s2) { return s1.operator== (s2.c()); }
|
||||
inline bool operator== (Symbol const& s1, Symbol const& s2) { return s1.c() == s2.c(); } ///< @note comparison of symbol table entries
|
||||
constexpr inline bool operator== (Literal const& s1, Literal const& s2) { return s1.operator== (s2.c()); }
|
||||
constexpr inline bool operator== (Symbol const& s1, Symbol const& s2) { return s1.c() == s2.c(); } ///< @note comparison of symbol table entries
|
||||
|
||||
/* === mixed comparisons === */
|
||||
|
||||
inline bool operator== (CStr s1, Literal s2) { return s2.operator== (s1); }
|
||||
inline bool operator== (Symbol s1, CStr s2) { return s1.operator== (s2); }
|
||||
inline bool operator== (CStr s1, Symbol s2) { return s2.operator== (s1); }
|
||||
inline bool operator== (Literal s1, Symbol s2) { return s1.operator== (s2.c()); }
|
||||
inline bool operator== (Symbol s1, Literal s2) { return s2.operator== (s1.c()); }
|
||||
inline bool operator== (Literal s1, std::string s2) { return s1.operator== (s2.c_str()); }
|
||||
inline bool operator== (std::string s1, Literal s2) { return s2.operator== (s1.c_str()); }
|
||||
inline bool operator== (Symbol s1, std::string s2) { return s1.operator== (s2.c_str()); }
|
||||
inline bool operator== (std::string s1, Symbol s2) { return s2.operator== (s1.c_str()); }
|
||||
|
||||
/* === negations === */
|
||||
|
||||
inline bool operator!= (Literal const& s1, Literal const& s2) { return not s1.operator== (s2.c()); }
|
||||
inline bool operator!= (Symbol const& s1, Symbol const& s2) { return not (s1.c() == s2.c()); }
|
||||
inline bool operator!= (Literal s1, CStr s2) { return not s1.operator== (s2); }
|
||||
inline bool operator!= (CStr s1, Literal s2) { return not s2.operator== (s1); }
|
||||
inline bool operator!= (Symbol s1, CStr s2) { return not s1.operator== (s2); }
|
||||
inline bool operator!= (CStr s1, Symbol s2) { return not s2.operator== (s1); }
|
||||
inline bool operator!= (Literal s1, Symbol s2) { return not s1.operator== (s2.c()); }
|
||||
inline bool operator!= (Symbol s1, Literal s2) { return not s2.operator== (s1.c()); }
|
||||
inline bool operator!= (Literal s1, std::string s2) { return not s1.operator== (s2.c_str()); }
|
||||
inline bool operator!= (std::string s1, Literal s2) { return not s2.operator== (s1.c_str()); }
|
||||
inline bool operator!= (Symbol s1, std::string s2) { return not s1.operator== (s2.c_str()); }
|
||||
inline bool operator!= (std::string s1, Symbol s2) { return not s2.operator== (s1.c_str()); }
|
||||
constexpr inline bool operator== (CStr s1, Literal s2) { return s2.operator== (s1); }
|
||||
constexpr inline bool operator== (Symbol s1, CStr s2) { return s1.operator== (s2); }
|
||||
constexpr inline bool operator== (Literal s1, Symbol s2) { return s1.operator== (s2.c()); }
|
||||
constexpr inline bool operator== (Literal s1, std::string const& s2) { return s1.operator== (s2.c_str()); }
|
||||
constexpr inline bool operator== (Symbol s1, std::string const& s2) { return s1.operator== (s2.c_str()); }
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ namespace lib {
|
|||
class ClassLock
|
||||
: public Sync<CONF>::Lock
|
||||
{
|
||||
using Lock = typename Sync<CONF>::Lock;
|
||||
using Monitor = typename sync::Monitor<CONF>;
|
||||
using Lock = Sync<CONF>::Lock;
|
||||
using Monitor = sync::Monitor<CONF>;
|
||||
|
||||
struct PerClassMonitor : Monitor {};
|
||||
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ namespace test{
|
|||
}
|
||||
|
||||
EventMatch&
|
||||
EventMatch::on (const char* targetID)
|
||||
EventMatch::on (CStr targetID)
|
||||
{
|
||||
refineSerach (solution_, matchAttribute("this",targetID));
|
||||
evaluateQuery ("match-this(\""+string(targetID)+"\")");
|
||||
|
|
@ -663,7 +663,7 @@ namespace test{
|
|||
}
|
||||
|
||||
EventLog&
|
||||
EventLog::clear (const char* alteredLogID)
|
||||
EventLog::clear (CStr alteredLogID)
|
||||
{
|
||||
return clear (string{alteredLogID});
|
||||
}
|
||||
|
|
@ -700,7 +700,7 @@ namespace test{
|
|||
}
|
||||
|
||||
EventLog&
|
||||
EventLog::call (const char* target, const char* function, ArgSeq&& args)
|
||||
EventLog::call (CStr target, CStr function, ArgSeq&& args)
|
||||
{
|
||||
return call (string(target), string(function), std::forward<ArgSeq>(args));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ namespace test{
|
|||
EventMatch& attrib (string key, string valueMatch);
|
||||
EventMatch& id (string classifier);
|
||||
EventMatch& on (string targetID);
|
||||
EventMatch& on (const char* targetID);
|
||||
EventMatch& on (CStr targetID);
|
||||
|
||||
template<typename X>
|
||||
EventMatch& on (const X *const targetObj)
|
||||
|
|
@ -298,7 +298,7 @@ namespace test{
|
|||
EventLog (string logID);
|
||||
|
||||
explicit
|
||||
EventLog (const char* logID)
|
||||
EventLog (CStr logID)
|
||||
: EventLog(string(logID))
|
||||
{ }
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ namespace test{
|
|||
/** purge log contents while retaining just the original Header-ID */
|
||||
EventLog& clear();
|
||||
EventLog& clear (string alteredLogID);
|
||||
EventLog& clear (const char* alteredLogID);
|
||||
EventLog& clear (CStr alteredLogID);
|
||||
|
||||
template<class X>
|
||||
EventLog&
|
||||
|
|
@ -372,7 +372,7 @@ namespace test{
|
|||
/** Log a function call with a sequence of stringified arguments */
|
||||
EventLog& call (string target, string function, ArgSeq&& args);
|
||||
|
||||
EventLog& call (const char* target, const char* function, ArgSeq&& args);
|
||||
EventLog& call (CStr target, CStr function, ArgSeq&& args);
|
||||
|
||||
/** Log a function call with arbitrary arguments */
|
||||
template<typename...ARGS>
|
||||
|
|
@ -392,7 +392,7 @@ namespace test{
|
|||
|
||||
template<typename...ARGS>
|
||||
EventLog&
|
||||
call (const char* target, string function, ARGS const& ...args)
|
||||
call (CStr target, string function, ARGS const& ...args)
|
||||
{
|
||||
return call (string(target), function, args...);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace microbenchmark {
|
|||
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
|
||||
static_assert (lib::meta::_Fun<FUN>::ARITY <=1, "Function with zero or one argument required.");
|
||||
|
||||
using Sig = typename lib::meta::_Fun<FUN>::Sig;
|
||||
using Sig = lib::meta::_Fun<FUN>::Sig;
|
||||
|
||||
return Adaptor<Sig>::wrap (std::forward<FUN> (fun));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ namespace test{
|
|||
*/
|
||||
template<typename T>
|
||||
inline string
|
||||
showSizeof (T const* obj =0, const char* name =0)
|
||||
showSizeof (T const* obj =0, CStr name =0)
|
||||
{
|
||||
return showSizeof (obj? sizeof(*obj) : sizeof(T),
|
||||
name? name : util::typeStr(obj));
|
||||
|
|
@ -114,14 +114,14 @@ namespace test{
|
|||
template<typename T>
|
||||
inline meta::disable_if<std::is_pointer<T>,
|
||||
string > // note:: force invocations with pointer to the first overload
|
||||
showSizeof (T const& obj, const char* name=0)
|
||||
showSizeof (T const& obj, CStr name =nullptr)
|
||||
{
|
||||
return showSizeof (&obj, name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline string
|
||||
showSizeof (const char* name)
|
||||
showSizeof (CStr name)
|
||||
{
|
||||
return showSizeof<T> (nullptr, name);
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ namespace test{
|
|||
showType()
|
||||
{
|
||||
using Case = TypeDiagnostics<X>;
|
||||
using Type = typename Case::Type;
|
||||
using Type = Case::Type;
|
||||
|
||||
return Case::prefix
|
||||
+ meta::humanReadableTypeID (typeid(Type).name())
|
||||
|
|
@ -375,7 +375,7 @@ namespace test{
|
|||
* \endcode
|
||||
*/
|
||||
inline lib::test::ExpectString
|
||||
operator""_expect (const char* lit, size_t siz)
|
||||
operator""_expect (CStr lit, size_t siz)
|
||||
{
|
||||
return lib::test::ExpectString{lit, siz};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,10 +372,10 @@ namespace lib {
|
|||
class InstanceCore
|
||||
{
|
||||
using ActionIter = IndexIter<const ActionSeq>;
|
||||
using DataCtxIter = typename SRC::Iter;
|
||||
using DataCtxIter = SRC::Iter;
|
||||
using NestedCtx = std::pair<DataCtxIter, SRC>;
|
||||
using CtxStack = std::stack<NestedCtx, std::vector<NestedCtx>>;
|
||||
using Value = typename SRC::Value;
|
||||
using Value = SRC::Value;
|
||||
|
||||
SRC dataSrc_;
|
||||
ActionIter actionIter_;
|
||||
|
|
@ -826,7 +826,7 @@ namespace lib {
|
|||
|
||||
/** Instantiate next Action token and expose its rendering */
|
||||
template<class SRC>
|
||||
inline typename SRC::Value
|
||||
inline SRC::Value
|
||||
TextTemplate::InstanceCore<SRC>::instantiateNext()
|
||||
{
|
||||
return actionIter_? actionIter_->instantiate(*this)
|
||||
|
|
@ -840,7 +840,7 @@ namespace lib {
|
|||
* @return the rendering produced by the selected next Action token
|
||||
*/
|
||||
template<class SRC>
|
||||
inline typename SRC::Value
|
||||
inline SRC::Value
|
||||
TextTemplate::InstanceCore<SRC>::reInstatiate (Idx nextCode)
|
||||
{
|
||||
if (nextCode == Idx(-1))
|
||||
|
|
@ -852,7 +852,7 @@ namespace lib {
|
|||
|
||||
/** retrieve a data value from the data source for the indiated key */
|
||||
template<class SRC>
|
||||
inline typename SRC::Value
|
||||
inline SRC::Value
|
||||
TextTemplate::InstanceCore<SRC>::getContent (string key)
|
||||
{
|
||||
static Value nil{};
|
||||
|
|
|
|||
|
|
@ -523,13 +523,13 @@ namespace lib {
|
|||
static_assert(1 == _Fun<FUN>::ARITY);
|
||||
static_assert(1 >= _Fun<HOOK>::ARITY);
|
||||
// argument type expected by the hooks down in the policy class
|
||||
using Arg = typename _Fun<FUN>::Args::List::Head;
|
||||
using Arg = _Fun<FUN>::Args::List::Head;
|
||||
// distinguish if user provided functor takes zero or one argument
|
||||
if constexpr (0 == _Fun<HOOK>::ARITY)
|
||||
return [hook = forward<HOOK>(hook)](Arg){ hook(); };
|
||||
else
|
||||
{ // instance type expected by the user-provided hook
|
||||
using Target = typename _Fun<HOOK>::Args::List::Head;
|
||||
using Target = _Fun<HOOK>::Args::List::Head;
|
||||
return [hook = forward<HOOK>(hook)]
|
||||
(Arg& threadWrapper)
|
||||
{ // build a two-step cast path from the low-level wrapper to user type
|
||||
|
|
@ -764,7 +764,7 @@ namespace lib {
|
|||
inline void
|
||||
launchDetached (string const& threadID, INVO&& ...args)
|
||||
{
|
||||
using Launch = typename TAR::Launch;
|
||||
using Launch = TAR::Launch;
|
||||
launchDetached<TAR> (Launch{forward<INVO> (args)...}
|
||||
.threadID (threadID));
|
||||
}
|
||||
|
|
@ -774,7 +774,7 @@ namespace lib {
|
|||
inline void
|
||||
launchDetached (string const& threadID, void (TAR::*memFun) (ARGS...), ARGS ...args)
|
||||
{
|
||||
using Launch = typename TAR::Launch;
|
||||
using Launch = TAR::Launch;
|
||||
launchDetached<TAR> (Launch{std::move (memFun)
|
||||
,lib::meta::InstancePlaceholder<TAR>{}
|
||||
,forward<ARGS> (args)...
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace mutation {
|
|||
TI
|
||||
operator() (TI const& changedVal) const
|
||||
{
|
||||
typedef typename ListenerList::const_iterator Iter;
|
||||
using Iter = ListenerList::const_iterator;
|
||||
Iter p = listeners_.begin();
|
||||
Iter e = listeners_.end();
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
#include "lib/symbol.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
|
@ -215,7 +214,6 @@ namespace time {
|
|||
, class FMT = digxel::Formatter<NUM>
|
||||
>
|
||||
class Digxel
|
||||
: public boost::totally_ordered<Digxel<NUM,FMT>>
|
||||
{
|
||||
mutable
|
||||
FMT buffer_;
|
||||
|
|
@ -297,9 +295,9 @@ namespace time {
|
|||
NUM operator++ (int) { NUM p(value_); *this =p+1; return p;}
|
||||
NUM operator-- (int) { NUM p(value_); *this =p-1; return p;}
|
||||
|
||||
//---Supporting-totally_ordered---------
|
||||
bool operator< (Digxel const& o) const { return value_ < NUM(o); }
|
||||
bool operator== (Digxel const& o) const { return value_ == NUM(o); }
|
||||
//---Supporting-total-ordering----------
|
||||
auto operator<=>(Digxel const& o) const { return value_ <=> NUM(o); }
|
||||
bool operator== (Digxel const& o) const { return value_ == NUM(o); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ namespace time {
|
|||
static Supported
|
||||
formats()
|
||||
{
|
||||
typedef typename TY::List SupportedFormats;
|
||||
using SupportedFormats = TY::List;
|
||||
return Supported().define(SupportedFormats());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@
|
|||
#include "lib/time/timecode.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
|
||||
//#include <boost/operators.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
|
@ -102,7 +101,7 @@ namespace time {
|
|||
bool supports() const; ///< does our implicit time grid support building that timecode format?
|
||||
|
||||
template<class FMT>
|
||||
typename format::Traits<FMT>::TimeCode
|
||||
format::Traits<FMT>::TimeCode
|
||||
formatAs() const; ///< create new time code instance, then #castInto
|
||||
|
||||
template<class TC>
|
||||
|
|
@ -134,10 +133,10 @@ namespace time {
|
|||
|
||||
|
||||
template<class FMT>
|
||||
inline typename format::Traits<FMT>::TimeCode
|
||||
inline format::Traits<FMT>::TimeCode
|
||||
QuTime::formatAs() const
|
||||
{
|
||||
using TC = typename format::Traits<FMT>::TimeCode;
|
||||
using TC = format::Traits<FMT>::TimeCode;
|
||||
return TC(*this);
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +154,7 @@ namespace time {
|
|||
inline void
|
||||
QuTime::castInto (TC& timecode) const
|
||||
{
|
||||
using Format = typename TC::Format;
|
||||
using Format = TC::Format;
|
||||
REQUIRE (supports<Format>());
|
||||
|
||||
Format::rebuild (timecode, *quantiser_, TimeValue(*this));
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
#include <compare>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -139,8 +140,6 @@ namespace time {
|
|||
* @see TimeVar when full arithmetics are required
|
||||
*/
|
||||
class TimeValue
|
||||
: boost::totally_ordered<TimeValue,
|
||||
boost::totally_ordered<TimeValue, raw_time_64>>
|
||||
{
|
||||
protected:
|
||||
/** the raw (internal) time value
|
||||
|
|
@ -196,12 +195,12 @@ namespace time {
|
|||
/** @return is in-domain, not a boundary value */
|
||||
bool isRegular() const;
|
||||
|
||||
// Supporting totally_ordered
|
||||
friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
|
||||
friend bool operator< (TimeValue const& t1, raw_time_64 t2) { return t1.t_ < t2 ; }
|
||||
friend bool operator> (TimeValue const& t1, raw_time_64 t2) { return t1.t_ > t2 ; }
|
||||
friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
|
||||
friend bool operator== (TimeValue const& t1, raw_time_64 t2) { return t1.t_ == t2 ; }
|
||||
// Supporting strong total ordering
|
||||
std::strong_ordering operator<=> (TimeValue const&) const =default;
|
||||
bool operator== (TimeValue const&) const =default;
|
||||
|
||||
std::strong_ordering operator<=> (raw_time_64 tt) const { return t_ <=> tt; }
|
||||
bool operator== (raw_time_64 tt) const { return t_ == tt; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -582,7 +581,6 @@ namespace time {
|
|||
*/
|
||||
class TimeSpan
|
||||
: public Time
|
||||
, boost::totally_ordered<TimeSpan>
|
||||
{
|
||||
Duration dur_;
|
||||
|
||||
|
|
@ -651,10 +649,15 @@ namespace time {
|
|||
/** @internal diagnostics */
|
||||
explicit operator std::string() const;
|
||||
|
||||
/// Supporting extended total order, based on start and interval length
|
||||
friend bool operator== (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_==t2.t_ && t1.dur_==t2.dur_; }
|
||||
friend bool operator< (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_< t2.t_ ||
|
||||
(t1.t_==t2.t_ && t1.dur_< t2.dur_);}
|
||||
/// Supporting extended strong total ordering, based on start and interval length
|
||||
std::strong_ordering
|
||||
operator<=> (TimeSpan const& ts) const
|
||||
{
|
||||
auto ord{ t_ <=> ts.t_ };
|
||||
return ord != 0? ord
|
||||
: dur_ <=> ts.dur_;
|
||||
}
|
||||
bool operator== (TimeSpan const& ts) const =default;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ namespace lib {
|
|||
}
|
||||
|
||||
friend string
|
||||
operator+ (const char* prefix, FamilyMember id)
|
||||
operator+ (CStr prefix, FamilyMember id)
|
||||
{
|
||||
return string(prefix)+id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ namespace util {
|
|||
template<typename T>
|
||||
struct treat_as_STL_Container
|
||||
{
|
||||
typedef typename lib::meta::Unwrap<T>::Type TaT;
|
||||
typedef lib::meta::Unwrap<T>::Type TaT;
|
||||
|
||||
enum{ value = lib::meta::can_STL_ForEach<TaT>::value
|
||||
&&!lib::meta::can_IterForEach<T>::value
|
||||
|
|
@ -71,7 +71,7 @@ namespace util {
|
|||
template<typename T>
|
||||
struct can_direct_access_Last
|
||||
{
|
||||
typedef typename lib::meta::Unwrap<T>::Type TaT;
|
||||
typedef lib::meta::Unwrap<T>::Type TaT;
|
||||
|
||||
enum{ value = lib::meta::can_STL_backIteration<TaT>::value
|
||||
};
|
||||
|
|
@ -159,7 +159,7 @@ namespace util {
|
|||
inline auto
|
||||
max (IT&& elms)
|
||||
{
|
||||
using Val = typename std::remove_reference_t<IT>::value_type;
|
||||
using Val = std::remove_reference_t<IT>::value_type;
|
||||
Val res = std::numeric_limits<Val>::min();
|
||||
for (auto const& elm : std::forward<IT> (elms))
|
||||
if (elm > res)
|
||||
|
|
@ -171,7 +171,7 @@ namespace util {
|
|||
inline auto
|
||||
max (CON const& elms)
|
||||
{
|
||||
using Val = typename std::remove_reference_t<CON>::value_type;
|
||||
using Val = std::remove_reference_t<CON>::value_type;
|
||||
Val res = std::numeric_limits<Val>::min();
|
||||
for (auto const& elm : elms)
|
||||
if (elm > res)
|
||||
|
|
@ -184,7 +184,7 @@ namespace util {
|
|||
inline auto
|
||||
min (IT&& elms)
|
||||
{
|
||||
using Val = typename std::remove_reference_t<IT>::value_type;
|
||||
using Val = std::remove_reference_t<IT>::value_type;
|
||||
Val res = std::numeric_limits<Val>::max();
|
||||
for (auto const& elm : std::forward<IT> (elms))
|
||||
if (elm < res)
|
||||
|
|
@ -196,7 +196,7 @@ namespace util {
|
|||
inline auto
|
||||
min (CON const& elms)
|
||||
{
|
||||
using Val = typename std::remove_reference_t<CON>::value_type;
|
||||
using Val = std::remove_reference_t<CON>::value_type;
|
||||
Val res = std::numeric_limits<Val>::max();
|
||||
for (auto const& elm : elms)
|
||||
if (elm < res)
|
||||
|
|
|
|||
|
|
@ -46,14 +46,14 @@ namespace std {// forward declarations to avoid pervasive includes
|
|||
}
|
||||
|
||||
|
||||
const char* cStr (std::string const&);
|
||||
using CStr = const char*;
|
||||
CStr cStr (std::string const&);
|
||||
|
||||
|
||||
|
||||
namespace util {
|
||||
|
||||
using std::string;
|
||||
using CStr = const char*;
|
||||
|
||||
|
||||
template <class NUM>
|
||||
|
|
@ -271,7 +271,7 @@ namespace util {
|
|||
|
||||
/** fetch value from a Map, or return a default if not found */
|
||||
template <typename MAP>
|
||||
inline typename MAP::mapped_type
|
||||
inline MAP::mapped_type
|
||||
getValue_or_default (MAP& map, typename MAP::key_type const& key
|
||||
, typename MAP::mapped_type defaultVal)
|
||||
{
|
||||
|
|
@ -288,7 +288,7 @@ namespace util {
|
|||
* @see lib::NullValue
|
||||
*/
|
||||
template <typename MAP>
|
||||
inline typename MAP::mapped_type const &
|
||||
inline MAP::mapped_type const &
|
||||
access_or_default (MAP& map, typename MAP::key_type const& key
|
||||
, typename MAP::mapped_type const& refDefault)
|
||||
{
|
||||
|
|
@ -302,7 +302,7 @@ namespace util {
|
|||
/** shortcut for removing all copies of an Element
|
||||
* in any sequential collection */
|
||||
template <typename SEQ>
|
||||
inline typename SEQ::iterator
|
||||
inline SEQ::iterator
|
||||
removeall (SEQ& coll, typename SEQ::value_type const& val)
|
||||
{
|
||||
typename SEQ::iterator collEnd = coll.end();
|
||||
|
|
@ -318,7 +318,7 @@ namespace util {
|
|||
template<class SET, typename FUN>
|
||||
bool remove_if (SET& set, FUN test)
|
||||
{
|
||||
typedef typename SET::iterator Itor;
|
||||
using Itor = SET::iterator;
|
||||
bool found = false;
|
||||
Itor end = set.end();
|
||||
Itor begin = set.begin();
|
||||
|
|
|
|||
|
|
@ -221,9 +221,9 @@ namespace lib {
|
|||
};
|
||||
|
||||
template<typename RET>
|
||||
using VisitorFunc = typename variant::VFunc<RET>::template VisitorInterface<TYPES>;
|
||||
using VisitorFunc = variant::VFunc<RET>::template VisitorInterface<TYPES>;
|
||||
template<typename RET>
|
||||
using VisitorConstFunc = typename variant::VFunc<RET>::template VisitorInterface<meta::ConstAll<typename TYPES::List>>;
|
||||
using VisitorConstFunc = variant::VFunc<RET>::template VisitorInterface<meta::ConstAll<typename TYPES::List>>;
|
||||
|
||||
/**
|
||||
* to be implemented by the client for visitation
|
||||
|
|
@ -443,7 +443,7 @@ namespace lib {
|
|||
|
||||
Variant()
|
||||
{
|
||||
using DefaultType = typename TYPES::List::Head;
|
||||
using DefaultType = TYPES::List::Head;
|
||||
|
||||
new(storage_) Buff<DefaultType> (DefaultType());
|
||||
}
|
||||
|
|
@ -453,7 +453,7 @@ namespace lib {
|
|||
{
|
||||
static_assert (variant::CanBuildFrom<X, TYPES>(), "No type in Typelist can be built from the given argument");
|
||||
|
||||
using StorageType = typename variant::CanBuildFrom<X, TYPES>::Type;
|
||||
using StorageType = variant::CanBuildFrom<X, TYPES>::Type;
|
||||
|
||||
new(storage_) Buff<StorageType> (forward<X>(x));
|
||||
}
|
||||
|
|
@ -477,7 +477,7 @@ namespace lib {
|
|||
Variant&
|
||||
operator= (X x)
|
||||
{
|
||||
using RawType = typename std::remove_reference<X>::type;
|
||||
using RawType = std::remove_reference<X>::type;
|
||||
static_assert (meta::isInList<RawType, typename TYPES::List>(),
|
||||
"Type error: the given variant could never hold the required type");
|
||||
static_assert (std::is_copy_assignable<RawType>::value, "target type does not support assignment");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue