From f9d0d135017ee1c2088b63bc973a53ac2f79ec67 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 3 May 2015 05:24:06 +0200 Subject: [PATCH] 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. --- LICENSE | 7 +++ src/lib/diff/tree-mutator.hpp | 46 +++++++++++++------ .../diff/generic-tree-mutator-test.cpp | 2 +- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/LICENSE b/LICENSE index 46ec7c294..aa23fae45 100644 --- a/LICENSE +++ b/LICENSE @@ -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* +- 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 + *The Loki Library* (C) 2001 by *Andrei Alexandrescu* diff --git a/src/lib/diff/tree-mutator.hpp b/src/lib/diff/tree-mutator.hpp index f597b155b..6469de18f 100644 --- a/src/lib/diff/tree-mutator.hpp +++ b/src/lib/diff/tree-mutator.hpp @@ -135,26 +135,46 @@ namespace diff{ namespace { - template + /** + * 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 + struct _ClosureType + : _ClosureType + { }; + + template + struct _ClosureType + { + typedef ARG ArgType; + typedef RET ReturnType; + }; + + + template struct ChangeOperation : PAR { - using Closure = function; - ID attribID_; - Closure change_; + CLO change_; virtual void setAttribute (ID id, Attribute& newValue) { + using ValueType = typename _ClosureType::ArgType; + if (id == attribID_) - change_(newValue.get()); + change_(newValue.get()); else // delegate to other closures (Decorator-style) PAR::setAttribute(id, newValue); } - ChangeOperation(ID id, Closure clo, PAR const& chain) + ChangeOperation(ID id, CLO clo, PAR const& chain) : PAR(chain) , attribID_(id) , change_(clo) @@ -169,19 +189,17 @@ namespace diff{ : PAR(par) { } - template - using Change = ChangeOperation; - template - using Closure = typename Change::Closure; + template + using Change = ChangeOperation; /* ==== binding API ==== */ - template - Builder> - change (Literal attributeID, Closure closure) + template + Builder> + change (Literal attributeID, CLO closure) { - return Change (attributeID, closure, *this); + return Change (attributeID, closure, *this); } }; diff --git a/tests/library/diff/generic-tree-mutator-test.cpp b/tests/library/diff/generic-tree-mutator-test.cpp index bd41ebf58..e06406196 100644 --- a/tests/library/diff/generic-tree-mutator-test.cpp +++ b/tests/library/diff/generic-tree-mutator-test.cpp @@ -92,7 +92,7 @@ namespace test{ string localData; auto mutator = TreeMutator::build() - .change("data", [&](string val) + .change("data", [&](string val) { cout << "\"data\" closure received something "<