
On Thu, Aug 26, 2010 at 11:52 AM, Adam Butcher <dev.lists@jessamine.co.uk> wrote:
On Thu, August 26, 2010 12:49 am, Lorenzo Caminiti wrote:
I am trying to use Boost.ScopeExit parameter binding mechanism to implement Boost.LocalFunction. To do so, I need to use some internal ScopeExit code to detect the type of `this` and bind its value to the local function declaration.
<snip>
2) Do you know of a workaround for this problem?
I posted a workaround for this a while back (http://lists.boost.org/Archives/boost/2009/03/149540.php) which used type indexing (where the index for typeof(this) is captured outside of a template parameter list) to avoid specifying 'this' in a template parameter list. The mechanics for the solution came from boost.typeof. However, the 'most preferred/natural syntax' relied on the somewhat rude definition of a function-style macro named 'this' (to support detection of the presence of 'this' as the first element of a preprocessor sequence) which, whilst innocuous, violates 17.4.3.1.1: 'Nor shall such a translation unit define macros for names lexically identical to keywords.' This may not be an issue for localfunction if you are always capturing 'this' or have a distinct interface for it's use in member functions.
You should also be able to modify your patch to use the following `IS_TRAILING_THIS` macro to check if `this` is passed within the `SCOPE_EXIT` sequence so you don't have to `#define this() ...`: #include <boost/preprocessor/detail/is_unary.hpp> #include <boost/preprocessor/cat.hpp> #define this_CONTRACT_DETAIL_PP_KEYWORD_THIS (1) #define CONTRACT_DETAIL_PP_KEYWORD_CHECK_BACK(tokens, keyword_postfix) \ BOOST_PP_IS_UNARY(BOOST_PP_CAT(tokens, keyword_postfix)) #define CONTRACT_DETAIL_PP_KEYWORD_IS_TRAILING_THIS(tokens) \ CONTRACT_DETAIL_PP_KEYWORD_CHECK_BACK(tokens, \ _CONTRACT_DETAIL_PP_KEYWORD_THIS) Given `SCOPE_EXIT(seq)` you can `SEQ_FOR_EACH(..., seq)` and apply `IS_TRAILING_THIS(elem)` for each `elem` in `seq`. Then `IS_TRAILING_THIS(this)` will expand to 1 while `IS_TRAILING(x)` `IS_TRAILING(&x)`, etc will all expand to 0. So you can check if an elem of seq is the token `this` or not and if it is you expand the `SCOPE_EXIT` to code that handles `this` (as you do now in your patch but without relying of `#define this() ...`).
I have attached my latest version of the patch which still applies fine to 1.44 and, I think, works on cl versions from vc7.1 upwards.
You should be able to use the same type index trick in localfunction. The key definition is the function-style macro BOOST_SCOPE_EXIT_TYPEDEF_TYPEOF_THIS().
Yes, I got the following example to compile: #include <contract/detail/se/scope_exit.hpp> // This header uses you patch for both scope_exit and typeof. //#include <boost/scope_exit.hpp> #include <iostream> struct c { c(): x_(0) {} bool eq(int x) { std::cout << "eq" << std::endl; return x_ == x; } void f(int& x) { std::cout << "f" << std::endl; x = -1; BOOST_SCOPE_EXIT( (this)(&x) ) { if (x < 0) x = 0; // These don't work :( //eq(x); //this->eq(x); //(*this).eq(x); // These work but syntax is not natural... operator->()->eq(x); operator*()->eq(x); std::cout << "se" << std::endl; } BOOST_SCOPE_EXIT_END } private: int x_; }; int main() { c cc; int x = 0; cc.f(x); return 0; } However, the syntax to access the object `this` inside scope exit needs to explicitly call the `operator->` or `operator*`... that's ugly so I am using a special name `this_` inside my local functions. *** Am I missing something? Can you access `this` from within the scope exit code without calling the operators directly? *** -- Lorenzo