[local_function] how bad is this `static_cast<>`?

Hello all, How bad is the `static_cast<>` below? struct c { void g() {} void f() { struct l: c { // Local function class wrapper. void body() { g(); // Usual implicit `this` access. this->g(); // Usual explicit `this` access. } }; static_cast<l*>(this)->body(); // *** HOW BAD IS THIS `STATIC_CAST<>`? *** } }; Could Boost.LocalFunction internally use such a technique when a special configuration macro is #defined by the users? IMO, if this `static_cast<>` can really corrupt memory on some systems/compilers, maybe Boost.LocalFunction should *never* use it. Otherwise, what would the documentation say "WARNING: If you #define this configuration macro, memory could be corrupted in some unknown way on some unknown combination of systems/compilers..." -- it's like providing a self-destruction button with a random countdown sequence via the configuration macro! What do you think? BACKGROUND Boost.LocalFunction can internally use this `static_cast<>` to provide access to the bound `this` parameter using the usual C++ syntax instead of the special name `this_`: #define BOOST_LOCAL_FUNCTION_CONFIG_IMPLICIT_THIS_HACK #include <boost/local_function.hpp> struct c { c(): x_(0.0) {} // Non-const member can bind `this` as non-const-bound. void f(double x) { double y = x + 10.0; BOOST_LOCAL_FUNCTION( (double) (total)( (int)(offset) (const bound)((&x)) (bound)((this)(y)) ) ) { reset(); // (1) Implicit `this`. this->x_ = x; // (2) Explicit `this`. assert(this_->equal(x)); // Also `this_`. double tot = x + y + offset; return tot; } BOOST_LOCAL_FUNCTION_END(total) double tot = total(100.0); std::cout << tot << std::endl; } void reset() { x_ = 0.0; } bool equal(double x) const { return x_ == x; } private: double x_; }; But if `BOOST_LOCAL_FUNCTION_CONFIG_IMPLICIT_THIS_HACK` is left #undefined (default) then line (1) and (2) must use `this_`: this_->reset(); this_->x_ = x; REFERENCE This code was originally proposed to me by Anthony Williams in order to access the outer class `this` object from within the local function: On Jul 29, 11:05 am, Anthony Williams <anthony....@gmail.com> wrote:
Lorenzo Caminiti <lorcamin...@gmail.com> writes:
However, ideally the code expression passed to `BLOCK_INVARIANT()` will looks the exactly the same as the code programmed within `f()`. Therefore, `this_->eq(x)` will ideally be `this->eq(x)`. Is there a way I can do this without inheriting `block_inv` from `c`? And that is what I need.
No, you cannot do that. "this" refers to an instance of the currentclass. Inside member functions of a localclass, "this" refers to an instance of that localclass.
You can do it with a nasty (i.e. strictly undefined behaviour, but works in practice) hack though: if your localclasshas no data members and no virtual functions then you can derive the localclassfrom theouterclassand cast your "this" pointer to be an instance of the localclass:
#include <iostream> class X { private: void g() const { std::cout<<"g(), this="<<this<<std::endl; } public: void f() { std::cout<<"f(), this="<<this<<std::endl; struct local:X { void foo() const { this->g(); } };
local const* p=static_cast<local const*>(const_cast<X const*>(this)); p->foo(); }
};
int main() { X x; x.f();
}
Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
[ Seehttp://www.gotw.ca/resources/clcm.htmfor info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
See: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/... -- Lorenzo

AMDG Lorenzo Caminiti wrote:
How bad is the `static_cast<>` below?
struct c { void g() {}
void f() { struct l: c { // Local function class wrapper. void body() { g(); // Usual implicit `this` access. this->g(); // Usual explicit `this` access. } };
static_cast<l*>(this)->body(); // *** HOW BAD IS THIS `STATIC_CAST<>`? *** } };
Could Boost.LocalFunction internally use such a technique when a special configuration macro is #defined by the users?
IMO, if this `static_cast<>` can really corrupt memory on some systems/compilers, maybe Boost.LocalFunction should *never* use it. Otherwise, what would the documentation say "WARNING: If you #define this configuration macro, memory could be corrupted in some unknown way on some unknown combination of systems/compilers..." -- it's like providing a self-destruction button with a random countdown sequence via the configuration macro! What do you think?
The problem with code like this is that it can cause the optimizer to make incorrect assumptions and miscompile the code. I believe that this has been observed with gcc. In Christ, Steven Watanabe

On Thu, Sep 9, 2010 at 12:13 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Lorenzo Caminiti wrote:
How bad is the `static_cast<>` below?
struct c { void g() {}
void f() { struct l: c { // Local function class wrapper. void body() { g(); // Usual implicit `this` access. this->g(); // Usual explicit `this` access. } };
static_cast<l*>(this)->body(); // *** HOW BAD IS THIS `STATIC_CAST<>`? *** } };
Could Boost.LocalFunction internally use such a technique when a special configuration macro is #defined by the users?
IMO, if this `static_cast<>` can really corrupt memory on some systems/compilers, maybe Boost.LocalFunction should *never* use it. Otherwise, what would the documentation say "WARNING: If you #define this configuration macro, memory could be corrupted in some unknown way on some unknown combination of systems/compilers..." -- it's like providing a self-destruction button with a random countdown sequence via the configuration macro! What do you think?
The problem with code like this is that it can cause the optimizer to make incorrect assumptions and miscompile the code. I believe that this has been observed with gcc.
Does this means Booster will NOT accept such a code/hack? Please express the Boost community option about: 1) Is this code/hack acceptable if guarded by a CONFIG macro? 2) Is the syntax that require explicit use of the special name `this_` inside a local function acceptable? Supporting this hack (even when wrapped by the CONFIG macro) is starting to pose some serious implementation issues for Boost.LocalFunction (these have to do with allowing recursive local function calls, supporting `auto bound`, etc essentially because the `static_cast<>` will miserably fail if the class has member variables). This is an implementation hack so no wonder it's causing more and more issues... There could be ways around these issues but I need to know if the hack will eventually be accepted before I spend time investigating workarounds. I almost wish Boosters could conclude they will not want/accept the hack and they are willing to use `this_` so to make Boost.LocalFunction implementation easier :) . *** Please advice -- or ask questions if you need more information in order to advice. *** Thank you. -- Lorenzo

On 11/09/10 19:52, Lorenzo Caminiti wrote:
I almost wish Boosters could conclude they will not want/accept the hack and they are willing to use `this_` so to make Boost.LocalFunction implementation easier :) .
*** Please advice -- or ask questions if you need more information in order to advice. ***
I think requiring this_ is fine. I was a bit worried about the possibility of silent failure when people forget (quite likely to happen during refactoring) but luckily there are very few circumstances I can thing of where it wouldn't give a compile error when you accidentally use this (the two that spring to mind are printing out the value, and reinterpret_casting it). Still, if there were a way to make it impossible to use 'this' at all, that would be nice to avoid this risk (but I doubt you can). John Bytheway

On Sun, Sep 12, 2010 at 5:54 AM, John Bytheway <jbytheway+boost@gmail.com> wrote:
On 11/09/10 19:52, Lorenzo Caminiti wrote:
I almost wish Boosters could conclude they will not want/accept the hack and they are willing to use `this_` so to make Boost.LocalFunction implementation easier :) .
*** Please advice -- or ask questions if you need more information in order to advice. ***
I think requiring this_ is fine. I was a bit worried about the
Do other Boosters share the same opinion?
possibility of silent failure when people forget (quite likely to happen during refactoring) but luckily there are very few circumstances I can thing of where it wouldn't give a compile error when you accidentally use this (the two that spring to mind are printing out the value, and reinterpret_casting it). Still, if there were a way to make it impossible to use 'this' at all, that would be nice to avoid this risk (but I doubt you can).
Actually, if the CONFIG macro is left #undef (default) then `this_` must be used and the local function is implemented as a static function so `this` cannot be used at all (not even by mistake). For example, the code below generates this error on GCC: $ g++ -Wall -Werror -I./src example/local_function_/line.cpp example/local_function_/line.cpp: In static member function ‘static double c::f(double)::contractXlocal_function_functorXlineX::contractXlocal_function_castableX::contractXlocal_function_bodyX(int, const double&, int, c*)’: example/local_function_/line.cpp:27: error: ‘this’ is unavailable for static member functions struct c { c(): y_(0.0) {} double f(double x) { int offset = x > 0 ? +100 : -100; CONTRACT_DETAIL_LOCAL_FUNCTION( (double) (line)( (int)(slope) (const bound)((&x)(offset)) (bound)((this)) ) ) { double y = slope * x + offset; return this->y_ = y; // ERROR: `this` not available (must use `this_` instead). } CONTRACT_DETAIL_LOCAL_FUNCTION_END(line) return line(2); } private: double y_; }; -- Lorenzo
participants (3)
-
John Bytheway
-
Lorenzo Caminiti
-
Steven Watanabe