ability to pick up the attribute type from the closure/functor

The actual trick to make it work is to use decltype on the function operator
http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765

In addition, we now pick up the functor by template type and
store it under that very type. For one, this cuts the size
of the generated class by a factor of two. And it gives the
compiler the ability to inline a closure as much as is possible,
especially when the created Binder / Mutator lives in the same
reference frame the closure taps into.
This commit is contained in:
Fischlurch 2015-05-03 05:24:06 +02:00
parent f45884975b
commit f9d0d13501
3 changed files with 40 additions and 15 deletions

View file

@ -15,6 +15,13 @@ For a copy of the GPL Version 2 see the file COPYING
in addition they are also dual-licensed under *CC-By-SA 3* in addition they are also dual-licensed under *CC-By-SA 3*
- at various places, the implementation draws on solutions
and comments published at http://Stackoverflow.com[Stackoverflow] --
according to the http://stackexchange.com/legal[License Agreement] page,
any ``subscriber content'' on that site is provided under *CC-By-SA 3*..
We attribute significant usages of solutions published this way
in the doxygen comments of the relevant source code entities.
- Parts of the Implementation are heavily inspired by + - Parts of the Implementation are heavily inspired by +
*The Loki Library* (C) 2001 by *Andrei Alexandrescu* *The Loki Library* (C) 2001 by *Andrei Alexandrescu*

View file

@ -135,26 +135,46 @@ namespace diff{
namespace { namespace {
template<class PAR, typename VAL> /**
* Type rebinding helper to pick up the actual argument type.
* Works both for functors and for lambda expressions
* @remarks Solution proposed 10/2011 by \link http://stackoverflow.com/users/224671/kennytm user "kennytm" \endlink
* in this \link http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765
* answer on stackoverflow \endlink
*/
template<typename FUN>
struct _ClosureType
: _ClosureType<decltype(&FUN::operator())>
{ };
template<class C, class RET, class ARG>
struct _ClosureType<RET (C::*)(ARG) const>
{
typedef ARG ArgType;
typedef RET ReturnType;
};
template<class PAR, class CLO>
struct ChangeOperation struct ChangeOperation
: PAR : PAR
{ {
using Closure = function<void(VAL)>;
ID attribID_; ID attribID_;
Closure change_; CLO change_;
virtual void virtual void
setAttribute (ID id, Attribute& newValue) setAttribute (ID id, Attribute& newValue)
{ {
using ValueType = typename _ClosureType<CLO>::ArgType;
if (id == attribID_) if (id == attribID_)
change_(newValue.get<VAL>()); change_(newValue.get<ValueType>());
else // delegate to other closures (Decorator-style) else // delegate to other closures (Decorator-style)
PAR::setAttribute(id, newValue); PAR::setAttribute(id, newValue);
} }
ChangeOperation(ID id, Closure clo, PAR const& chain) ChangeOperation(ID id, CLO clo, PAR const& chain)
: PAR(chain) : PAR(chain)
, attribID_(id) , attribID_(id)
, change_(clo) , change_(clo)
@ -169,19 +189,17 @@ namespace diff{
: PAR(par) : PAR(par)
{ } { }
template<typename VAL> template<class CLO>
using Change = ChangeOperation<PAR,VAL>; using Change = ChangeOperation<PAR,CLO>;
template<typename VAL>
using Closure = typename Change<VAL>::Closure;
/* ==== binding API ==== */ /* ==== binding API ==== */
template<typename VAL> template<typename CLO>
Builder<Change<VAL>> Builder<Change<CLO>>
change (Literal attributeID, Closure<VAL> closure) change (Literal attributeID, CLO closure)
{ {
return Change<VAL> (attributeID, closure, *this); return Change<CLO> (attributeID, closure, *this);
} }
}; };

View file

@ -92,7 +92,7 @@ namespace test{
string localData; string localData;
auto mutator = auto mutator =
TreeMutator::build() TreeMutator::build()
.change<string>("data", [&](string val) .change("data", [&](string val)
{ {
cout << "\"data\" closure received something "<<val<<endl; cout << "\"data\" closure received something "<<val<<endl;
localData = val; localData = val;