|
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