Prev: Templates in application level code (was: Re: Any hopes for export ?)
Next: Why cannot I get initializer_list like objects without using them? Please, why wouldn't the code (1) below work with c++0x?
From: Lorenzo Caminiti on 26 Jul 2010 13:30 Hello all, I am new to this groups. I would like to post a C++ programming question. Is there a way to access the outer class `this` from a local class but without using inheritance? Let me explain with an example: class x { // outer class public: void g() {} void f() { this->g(); // (1) struct y: x { // local class but using inheritance... y(x* super): x(*super) {} // (2) void h() { this->g(); // (3) } }; y(this).h(); } }; *** Is there a way to do this but without inheriting `y` from `x`? *** At line (3), the local class `y` can access the outer class `x::g()` simply using `this` because `y` inherits from `x`. However, this inheritance requires to construct another object `x` when `y` is constructed as in line (2) adding runtime overhead and requiring `x` to have an accessible copy constructor. In my application, I need line (3) to essentially look the same as like line (1) so you can program code inside `y` members as if it were inside `x` members. A part from that, the local class `y` could look as it is needed to solve this problem -- with more member variables, member functions, etc. (For example, I tried to redefine `y::operator->()`/`y::operator*()` to return a pointer/reference to `x` but this does not work because `this->`/`*this` always retain pointer semantics and do not use the operators I redefined...) Thank you very much. -- Lorenzo [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran Pusic on 26 Jul 2010 23:43 > Hello all, > > I am new to this groups. I would like to post a C++ programming > question. > > Is there a way to access the outer class `this` from a local class but > without using inheritance? Bar "code organisation purposes", inner and outer classes have no connection between them, so, no. Your inner class has to have a reference to an instance of the outer class (or derive from it). > > Let me explain with an example: > > class x { // outer class > public: > void g() {} > > void f() { > this->g(); // (1) > > struct y: x { // local class but using inheritance... > y(x* super): x(*super) {} // (2) Using a reference seems a better option here. You never check super for NULL, and if you ever do y(NULL), you'll crash. In C++, you can make this design decision spelled out by the syntax. It is also unusual to construct a derived object by using a conversion constructor (fancy word for a constructor with one argument) that is receiving an instance of a base class, but seems justified given the context (albeit, context is IMO wrong). > void h() { > this->g(); // (3) g is already a public method of x. You could simply do this: struct y { y(x& xx) : _x(x) {} void h() { _x.g(); } x _x; } If g isn't public, and since you are already controlling both classes, you can make y a friend of x to be able to touch it's private parts. > At line (3), the local class `y` can access the outer class `x::g()` > simply using `this` because `y` inherits from `x`. However, this > inheritance requires to construct another object `x` when `y` is > constructed as in line (2) adding runtime overhead and requiring `x` > to have an accessible copy constructor. Well, you decided to create another object, what did you expect? ;-) > In my application, I need line (3) to essentially look the same as > like line (1) so you can program code inside `y` members as if it were > inside `x` members. A part from that, the local class `y` could look > as it is needed to solve this problem -- with more member variables, > member functions, etc. The thing is, like with many newbie questions, you think that you need line (3). But in fact, there's probably much more ways to achieve desired end result, overall (calling g() on an instance of x is just part of that result). In other words, you should consider changing your question so that it tells more about what you want to do. The question you asked is "can I do __this__ so that I can do __that__?". But __this__ is tangential (and trivial). > (For example, I tried to redefine `y::operator->()`/`y::operator*()` > to return a pointer/reference to `x` but this does not work because > `this->`/`*this` always retain pointer semantics and do not use the > operators I redefined...) Yeah, that's a dead end. HTH, Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 26 Jul 2010 23:43 On 27 Jul., 06:30, Lorenzo Caminiti <lorcamin...(a)gmail.com> wrote: > I am new to this groups. I would like to post a C++ programming > question. You are welcome to do so! > Is there a way to access the outer class `this` from a local class > but without using inheritance? > > Let me explain with an example: > > class x { // outer class > public: > void g() {} > > void f() { > this->g(); // (1) > > struct y: x { // local class but using inheritance... > y(x* super): x(*super) {} // (2) > void h() { > this->g(); // (3) > } > }; > y(this).h(); > } > }; > > *** Is there a way to do this but without inheriting `y` from `x`? *** Yes, but that requires that y has a constructor accepting a (reference or pointer to) x and has a member of pointer or reference type, e.g. like this: class x { // outer class public: void g() {} void f() { this->g(); // (1) struct y { // local class, no inheritance x* that; // References an object of the outer class y(x* super): that(super) {} // (2) void h() { that->g(); // (3) } }; y(this).h(); } }; Question: Do you have Java background, where it is possible to define a "non-static" inner class with implied constructor argument for an object of the outer class? > At line (3), the local class `y` can access the outer class `x::g()` > simply using `this` because `y` inherits from `x`. However, this > inheritance requires to construct another object `x` when `y` is > constructed as in line (2) adding runtime overhead and requiring `x` > to have an accessible copy constructor. Yes, and this idiom is not required. > In my application, I need line (3) to essentially look the same as > like line (1) so you can program code inside `y` members as if it were > inside `x` members. A part from that, the local class `y` could look > as it is needed to solve this problem -- with more member variables, > member functions, etc. But note that there are some restrictions to local classes, among them it is not feasible to have static data members. > (For example, I tried to redefine `y::operator->()`/`y::operator*()` > to return a pointer/reference to `x` but this does not work because > `this->`/`*this` always retain pointer semantics and do not use the > operators I redefined...) This should also work, you can simply define: x* operator->() const { return that; } as inline function in y. It is not possible to define any member functions outside of the local class, though. HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Anthony Williams on 26 Jul 2010 23:44 Lorenzo Caminiti <lorcaminiti(a)gmail.com> writes: > Is there a way to access the outer class `this` from a local class but > without using inheritance? Pass it in to the local class either as a constructor parameter or a function parameter: #include <iostream> class X { private: void g() { std::cout<<"g(), this="<<this<<std::endl; } public: void f() { std::cout<<"f(), this="<<this<<std::endl; struct local { X* self; local(X* self_): self(self_) {} void foo() { self->g(); } }; local y(this); y.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 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Lorenzo Caminiti on 28 Jul 2010 09:16
On Jul 27, 10:43 am, Goran Pusic <gor...(a)cse-semaphore.com> wrote: > > > In my application, I need line (3) to essentially look the same as > > like line (1) so you can program code inside `y` members as if it were > > inside `x` members. A part from that, the local class `y` could look > > as it is needed to solve this problem -- with more member variables, > > member functions, etc. > > The thing is, like with many newbie questions, you think that you need > line (3). But in fact, there's probably much more ways to achieve > desired end result, overall (calling g() on an instance of x is just > part of that result). In other words, you should consider changing > your question so that it tells more about what you want to do. The > question you asked is "can I do __this__ so that I can do __that__?". > But __this__ is tangential (and trivial). I want to program code inside `y` members as if it were inside `x` members. This is my only requirement. Here's more background information about what I want to do and why. BACKGROUND I am programming a macro which evaluates a code expression in constant- correct context by executing the code from within a local function by passing the object `this` and other variables as `const`. For example, the `BLOCK_INVARIANT()` macro can be programmed so that the following: class c { public: c(int x): x_(x) {} bool eq(int x) const { return x_ == x; }; void f(int x) { BLOCK_INVARIANT( (const (c*)(this) (int)(x) (this_->eq(x) == false)) ) } private: int x_; }; Expands to: class c { public: c(int x): x_(x) {} bool eq(int x) const { return x_ == x; }; void f(int x) { struct block_invariant { static void check(c const* const this_, int const& x) { if(!( this_->eq(x) == false )) { // Evaluated in constant-correct context because `this_` and `x` are `const`. throw int(-1); } } }; block_invariant::check(this, x); } private: int x_; }; Now the compiler will generate an error if the code expression passed to `BLOCK_INVARIANT()` -- `this_->eq(x)` in this example -- is not constant-correct. 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. REPLIES For example, thank you for the following suggestions but they do not work because: On Jul 27, 10:43 am, Daniel Kr�gler <daniel.krueg...(a)googlemail.com> wrote: > class x { // outer class > public: > void g() {} > > void f() { > this->g(); // (1) > > struct y { // local class, no inheritance > x* that; // References an object of the outer class > y(x* super): that(super) {} // (2) > void h() { > that->g(); // (3) > } > }; > y(this).h(); > } > }; Line (3) does not look the same as line (1). In other words, this solution does not work because I would use `that` inside `y` members and `this` inside `x` members so line (1) and (3) look different from each other. On Jul 27, 10:44 am, Anthony Williams <anthony....(a)gmail.com> wrote: > #include <iostream> > class X > { > private: > void g() > { > std::cout<<"g(), this="<<this<<std::endl; > } > public: > void f() > { > std::cout<<"f(), this="<<this<<std::endl; > struct local > { > X* self; > local(X* self_): > self(self_) > {} > > void foo() > { > self->g(); > } > }; > > local y(this); > y.foo(); > } > > }; Similarly, this does not work because `self->g()` from within the local function looks different from `this->g()` from within the non- local function. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |