Boost logo

Boost :

Subject: Re: [boost] [scope_exit] MSVC error C2355: 'this' : can only be referenced inside non-static member functions
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-09-17 11:33:56


On Thu, Aug 26, 2010 at 11:52 AM, Adam Butcher
<dev.lists_at_[hidden]> 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk