Investigation: dissect argument packs
start investigation on generic techniques to dissect an variadic argument pack
This commit is contained in:
parent
372512006f
commit
e5dc7ba2bc
5 changed files with 70 additions and 168 deletions
162
research/try.cpp
162
research/try.cpp
|
|
@ -32,15 +32,19 @@
|
|||
// 1/16 - generic to-string conversion for ostream
|
||||
// 1/16 - build tuple from runtime-typed variant container
|
||||
// 3/17 - generic function signature traits, including support for Lambdas
|
||||
// 9/17 - manipulate variadic templates to treat varargs in several chunks
|
||||
|
||||
|
||||
/** @file try.cpp
|
||||
** Metaprogramming: unified treatment of functors, function references and lambdas.
|
||||
** Rework our existing function signature trait to also support lambdas, which forces us
|
||||
** to investigate and in the end to change the handling of function member pointers.
|
||||
** Metaprogramming: manipulations on variadic template argument packs.
|
||||
** Investigation how to transform a parameter pack such as to forward a fixed chunk
|
||||
** to one sub-ctor and delegate the rest to a tail recursive call.
|
||||
**
|
||||
** This investigation is a partial step towards #994 and became necessary to support
|
||||
** Command definition by Lambda
|
||||
** This investigation was spurred by an attempt to create an inline storage layout
|
||||
** with possible heap-based extension. Being able to build such an object layout
|
||||
** would enable several possibly interesting optimisations when most usage scenarios
|
||||
** of a class will only use a small element count, while some usages still require
|
||||
** an essentially unlimited open number of elements.
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
@ -56,169 +60,21 @@ typedef unsigned int uint;
|
|||
using lib::meta::_Fun;
|
||||
|
||||
using std::function;
|
||||
using std::placeholders::_1;
|
||||
using std::bind;
|
||||
using std::string;
|
||||
using std::tuple;
|
||||
using std::move;
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
funny (uint i)
|
||||
{
|
||||
return -i+1;
|
||||
}
|
||||
|
||||
struct Funky
|
||||
{
|
||||
int ii = 2;
|
||||
|
||||
int
|
||||
fun (uint i2)
|
||||
{
|
||||
return ii + funny(i2);
|
||||
}
|
||||
|
||||
int
|
||||
operator() (uint i2)
|
||||
{
|
||||
return 2*ii - fun(i2);
|
||||
}
|
||||
|
||||
static int
|
||||
notfunny (uint i)
|
||||
{
|
||||
return 2*funny (i);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define SHOW_TYPE(_TY_) \
|
||||
cout << "typeof( " << STRINGIFY(_TY_) << " )= " << lib::meta::typeStr<_TY_>() <<endl;
|
||||
|
||||
#define EVAL_PREDICATE(_PRED_) \
|
||||
cout << STRINGIFY(_PRED_) << "\t : " << _PRED_ <<endl;
|
||||
|
||||
|
||||
template<typename F>
|
||||
void
|
||||
showType (F)
|
||||
{
|
||||
using Sig = typename _Fun<F>::Sig;
|
||||
|
||||
SHOW_TYPE (F);
|
||||
SHOW_TYPE (Sig);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void
|
||||
showRef (F&)
|
||||
{
|
||||
using Sig = typename _Fun<F>::Sig;
|
||||
|
||||
SHOW_TYPE (F);
|
||||
SHOW_TYPE (Sig);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void
|
||||
showCRef (F&)
|
||||
{
|
||||
using Sig = typename _Fun<F>::Sig;
|
||||
|
||||
SHOW_TYPE (F);
|
||||
SHOW_TYPE (Sig);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void
|
||||
showRRef (F&&)
|
||||
{
|
||||
using Sig = typename _Fun<F>::Sig;
|
||||
|
||||
SHOW_TYPE (F);
|
||||
SHOW_TYPE (Sig);
|
||||
}
|
||||
|
||||
|
||||
using Fun = function<int(uint)>;
|
||||
using Fuk = function<int(Funky&, uint)>;
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
Fun f1{funny};
|
||||
Fun f2{&funny};
|
||||
|
||||
Fun f3{Funky::notfunny};
|
||||
Fun f4{&Funky::notfunny};
|
||||
|
||||
auto memfunP = &Funky::fun;
|
||||
|
||||
Fuk f5{memfunP};
|
||||
|
||||
Funky funk;
|
||||
|
||||
Fun f6{bind (f5, funk, _1)};
|
||||
|
||||
auto lambda = [&](uint ii) { return funk.fun(ii); };
|
||||
|
||||
Fun f7{lambda};
|
||||
|
||||
showType (funny);
|
||||
showType (&funny);
|
||||
showType (Funky::notfunny);
|
||||
|
||||
showType (memfunP);
|
||||
showType (lambda);
|
||||
showType (f7);
|
||||
|
||||
cout << "\n\n-------\n";
|
||||
|
||||
showRef (funny);
|
||||
showRef (lambda);
|
||||
showRef (f7);
|
||||
|
||||
showCRef (funny);
|
||||
showCRef (lambda);
|
||||
showCRef (f7);
|
||||
|
||||
showRRef (move(lambda));
|
||||
showRRef (move(f7));
|
||||
|
||||
showType (move(&funny));
|
||||
showType (move(lambda));
|
||||
showType (move(f7));
|
||||
|
||||
Fun& funRef = f1;
|
||||
Funky& funkyRef = funk;
|
||||
Fun const& funCRef = f1;
|
||||
Funky const& funkyCRef = funk;
|
||||
showType (funRef);
|
||||
showType (funkyRef);
|
||||
showType (funCRef);
|
||||
showType (funkyCRef);
|
||||
|
||||
cout << "\n\n-------\n";
|
||||
|
||||
SHOW_TYPE (decltype(&Funky::operator()));
|
||||
SHOW_TYPE (decltype(lambda));
|
||||
|
||||
SHOW_TYPE (_Fun<int(uint)>::Sig);
|
||||
SHOW_TYPE (_Fun<Fun&>::Sig);
|
||||
SHOW_TYPE (_Fun<Fun&&>::Sig);
|
||||
SHOW_TYPE (_Fun<Fun const&>::Sig);
|
||||
SHOW_TYPE (_Fun<Funky&>::Sig);
|
||||
SHOW_TYPE (_Fun<Funky&&>::Sig);
|
||||
SHOW_TYPE (_Fun<Funky const&>::Sig);
|
||||
|
||||
using Siggy = _Fun<Fun>::Sig;
|
||||
SHOW_TYPE (_Fun<Siggy&>::Sig);
|
||||
SHOW_TYPE (_Fun<Siggy&&>::Sig);
|
||||
SHOW_TYPE (_Fun<Siggy const&>::Sig);
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -249,27 +249,25 @@ namespace meta {
|
|||
|
||||
|
||||
/**
|
||||
* Extensible Adapter to construct a distinct tuple
|
||||
* from some arbitrary source type. This includes the
|
||||
* possibility to re-map elements or element positions.
|
||||
* Extensible Adapter to construct a distinct tuple from some arbitrary source type.
|
||||
* This includes the possibility to re-map elements or element positions.
|
||||
* @tparam TYPES sequence of types to use for the tuple
|
||||
* @tparam _ElmMapper_ a _template_ to extract each
|
||||
* constructor argument from the source value.
|
||||
* On invocation, we'll pick up the source type from the
|
||||
* actual ctor argument, and then invoke this helper template
|
||||
* iteratively for each component of the tuple, with arguments
|
||||
* On invocation, we'll pick up the source type from the actual ctor argument,
|
||||
* and then invoke this helper template iteratively for each component of the
|
||||
* tuple, passing as template arguments
|
||||
* - the source type, as picked up from the constructor
|
||||
* - the target tuple type, i.e. `Tuple<TYPES>`
|
||||
* - the actual index position of the tuple element
|
||||
* to be initialised through this concrete instantiation.
|
||||
* @remarks this design has several extension points. Pretty much
|
||||
* any conceivable initialisation logic can be embodied in the
|
||||
* `_ElmMapper_` template. The sole requirement is that the
|
||||
* concrete instance is _assignable_ by the source type and
|
||||
* _convertible_ to the individual member type of the target
|
||||
* tuple it is invoked for. Moreover, it is possible to build
|
||||
* a generic _element extractor_, which will be specialised
|
||||
* on base of the source type accepted. See \ref ExtractArg
|
||||
* @remarks this design has several extension points. Pretty much any conceivable
|
||||
* initialisation logic can be embodied in the `_ElmMapper_` template. The sole
|
||||
* requirement is that the concrete instance is _assignable_ by the source type
|
||||
* and _convertible_ to the individual member type of the target tuple it is
|
||||
* invoked for. Moreover, it is possible to build a generic _element extractor_,
|
||||
* which will be specialised on base of the source type accepted.
|
||||
* @see ExtractArg
|
||||
*/
|
||||
template< typename TYPES
|
||||
, template<class,class, size_t> class _ElmMapper_
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@
|
|||
** @see typeseq-manip-test.cpp
|
||||
** @see typelist.hpp
|
||||
** @see typelist-util.hpp
|
||||
** @see tuple-helper.hpp
|
||||
** @see function.hpp
|
||||
** @see generator.hpp
|
||||
** @see tuple.hpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ namespace lib {
|
|||
using lib::Literal;
|
||||
|
||||
// class GlobalCtx;
|
||||
namespace { // Implementation helper: variadic init
|
||||
|
||||
}//(End)Implementation helper
|
||||
|
||||
|
||||
|
||||
|
|
@ -82,11 +85,13 @@ namespace lib {
|
|||
template<typename...ARGS>
|
||||
explicit
|
||||
PathArray (ARGS&& ...args)
|
||||
: elms_{}
|
||||
{
|
||||
UNIMPLEMENTED ("initialise path array components");
|
||||
}
|
||||
|
||||
PathArray (PathArray const& o)
|
||||
: elms_(o.elms_)
|
||||
{
|
||||
UNIMPLEMENTED ("copy construct path array components");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3831,6 +3831,49 @@
|
|||
<node CREATED="1506263953722" ID="ID_1293486815" MODIFIED="1506263959604" TEXT="Basis-Abstraktion"/>
|
||||
<node CREATED="1506263960121" ID="ID_381874562" MODIFIED="1506263965699" TEXT="PathArray">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1506301404246" ID="ID_458341734" MODIFIED="1506301409177" TEXT="Impl-Layout">
|
||||
<node CREATED="1506301410525" ID="ID_176098837" MODIFIED="1506301414840" TEXT="Rekursiv"/>
|
||||
<node CREATED="1506301415548" ID="ID_212757263" MODIFIED="1506301419912" TEXT="chunk-wise"/>
|
||||
</node>
|
||||
<node CREATED="1506301421612" ID="ID_572376877" MODIFIED="1506301426568" TEXT="Meta-Problem">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1506301428698" ID="ID_1290675306" MODIFIED="1506301433910" TEXT="Parameter-Pack zerlegen">
|
||||
<node CREATED="1506301435826" ID="ID_1852582857" MODIFIED="1506301447508" TEXT="ersten Teil in ein std::array"/>
|
||||
<node CREATED="1506301448288" ID="ID_1083459556" MODIFIED="1506301457058" TEXT="zweiten Teil rekursiv..."/>
|
||||
</node>
|
||||
<node CREATED="1506301468830" ID="ID_291609200" MODIFIED="1506301471937" TEXT="Lösungen">
|
||||
<node CREATED="1506301476836" ID="ID_1339982909" MODIFIED="1506302323712" TEXT="Stackoverflow">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1506301629128" ID="ID_1265747852" LINK="https://stackoverflow.com/questions/14261183/how-to-make-generic-computations-over-heterogeneous-argument-packs-of-a-variadic" MODIFIED="1506301640408" TEXT="Param-Pack-Library"/>
|
||||
<node CREATED="1506301658388" ID="ID_284261237" LINK="https://stackoverflow.com/users/1932150/andy-prowl" MODIFIED="1506301669997" TEXT="von Andy Prowl"/>
|
||||
<node CREATED="1506302060966" ID="ID_37516099" LINK="https://stackoverflow.com/questions/16821654/splitting-argpack-in-half/16980937#16980937" MODIFIED="1506302137771" TEXT="einfache Lösung: split Pack in half"/>
|
||||
<node CREATED="1506302079276" ID="ID_539701222" LINK="https://stackoverflow.com/users/2361316/joe" MODIFIED="1506302087043" TEXT="von User Joe"/>
|
||||
<node CREATED="1506303631812" ID="ID_1461128808" LINK="https://stackoverflow.com/questions/5484930/split-variadic-template-arguments/20814644#20814644" MODIFIED="1506303806992" TEXT="direkt initializer_list verwenden"/>
|
||||
<node CREATED="1506303644395" ID="ID_1907242246" LINK="https://stackoverflow.com/users/2684539/jarod42" MODIFIED="1506303675990" TEXT="von user Jarod42 12/2013"/>
|
||||
</node>
|
||||
<node CREATED="1506301674594" ID="ID_573792630" MODIFIED="1506301767802" TEXT="Boost.fusion verwenden">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1506301681345" ID="ID_1364627462" MODIFIED="1506301687084" TEXT="Param-Pack in Tupel"/>
|
||||
<node CREATED="1506301687720" ID="ID_1178221359" MODIFIED="1506301696419" TEXT="Tupel mit Boost.fustion manipulieren"/>
|
||||
<node CREATED="1506301696911" ID="ID_1626810109" MODIFIED="1506301705897" TEXT="Compiler optimiert Tupel weg">
|
||||
<node CREATED="1506301725107" ID="ID_1409951481" MODIFIED="1506301731668" TEXT="Tupel von Referenzen"/>
|
||||
<node CREATED="1506301713285" ID="ID_703461640" MODIFIED="1506301719136" TEXT="GCC und Clang"/>
|
||||
<node CREATED="1506301719660" ID="ID_1581101665" MODIFIED="1506301722999" TEXT="in Release-Builds"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1506301773341" ID="ID_515001314" MODIFIED="1506301831038" TEXT="Entscheidung">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1506301780644" ID="ID_143930610" MODIFIED="1506301822914" TEXT="Boost.fustion abgelehnt">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1506301789546" ID="ID_322419894" MODIFIED="1506301792558" TEXT="verwendet MPL"/>
|
||||
<node CREATED="1506301793130" ID="ID_1764621800" MODIFIED="1506301797158" TEXT="verwendet Boost.tuple"/>
|
||||
<node CREATED="1506301797721" ID="ID_1580459971" MODIFIED="1506301801941" TEXT="generell undurchsichtig"/>
|
||||
<node CREATED="1506301802865" ID="ID_1127036077" MODIFIED="1506301816915" TEXT="erfordert hohes Abstraktionsniveau"/>
|
||||
</node>
|
||||
<node CREATED="1506301834493" ID="ID_52512330" MODIFIED="1506301846055" TEXT="selber schreiben anhand Beispiel"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1506181727069" ID="ID_467120404" MODIFIED="1506181737140" TEXT="lokale Prädikate">
|
||||
|
|
|
|||
Loading…
Reference in a new issue