Re: pushing the limits of use-before-declaration within a class
From: Walt Karas (wkaras_at_yahoo.com)
Date: 09/05/04
- Next message: JKop: "Re: How can I achieve this behaviour?"
- Previous message: Kai-Uwe Bux: "Re: Is C++ fundamentally broken?:was:Re: C++ unit testing"
- In reply to: Matthew Hall: "Re: pushing the limits of use-before-declaration within a class"
- Next in thread: Conrad Weyns: "Re: pushing the limits of use-before-declaration within a class"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 5 Sep 2004 07:40:39 -0400
Matthew Hall <mahall@math.uiuc.edu> wrote in message news:<cha6vp$718$1@news.ks.uiuc.edu>...
> Walt Karas wrote:
> > Is this code legal under the standard?
> >
> > struct A
> > {
> > int i;
> >
> > struct C
> > {
> > unsigned offset_of_c(void) { return((unsigned) &(((A *) 0)->c)); }
> >
> > A * ptr_to_containing_A_instance(void)
> > { return((A *) (((char *) this) - offset_of_c())); }
> >
> > void set(void)
> > { ptr_to_containing_A_instance()->i = 10; }
> > }
> > c;
> (From my experience, 'struct C {...} c; is not very idiomatic C++. It is
> more common to split this into two statements - one defining the type
> and another declaring the member variable. See below for example)
>
> >
> > };
> >
> > #include <stdio.h>
> >
> > int main(void)
> > {
> > A a;
> >
> > a.c.set();
> >
> > // Should print 10.
> > printf("%d\n", a.i);
> >
> > return(0);
> > }
> >
> > The version of GCC I am using compiles and links it,
> > and the resulting executable produces the expected
> > output when run.
> >
> > Is there a less ugly way to implement a class that
> > is not only a member class but whose instance must
> > be in the containing class and access the containing
> > class's members?
>
> First, without questioning the design:
> Your code relies on the layout of your class. Since A is a POD in this
> case, this is OK (well, you use C-style casts and I/O). However, it is
> error prone and is not guaranteed to work once you add in virtual
> methods or multiple inheritence.
I'm relying on this principle being true:
T a, b;
assert((((char *) &a.x) - ((char *) &a)) ==
(((char *) &b.x) - ((char *) &b)));
It's hard to imagine a C++ implementation where this would ever
be false, even if T is a dynamic class or has multple inheritance.
> My preferred way would use constructors, and go something like this:
>
> struct A
> {
> int i;
>
> class C
> {
> public:
> C(A* parent) : m_parent(parent) {}
> void set(void) { m_parent->i = 10;}
> A* m_parent;
> };
> C c;
>
> A() : i(0), c(this){}
> };
The m_parent pointer seems like a waste of memory to me if C is never
going to be used again other than being the type of the member c. But
this is probably just due to the residual trauma of being old enough
to have own a PC with only 640K of RAM.
> Nice, portable code. (though not very good at data hiding)
>
> //Variants:
> // if A is a class with private data that c should access, add
> // 'friend class C' to A's declaration
> // Use a reference to A as opposed to a pointer.
>
> Granted, this does add some overhead in both execution speed of the
> construction, as well as in size, so if you need to create a billion of
> these things, you might want to take a different approach. In that case
> you might want to re-evaluate your use of a nested class/struct.
>
> I realize that you have probably provided a minimal example, but why not
> just use move the 'set' method into A, and use 'a.set()' instead of
> 'a.c.set()'.
> In fact, since A is a struct, why not create a free function set:
> void set(A& a) { a.i=10;}
> (Though the name 'set' should probably be changed, so as not to confuse
> humans and/or compilers who might first think of std::set)
>
> -matt
It's hard to give a short example illustrating why I want to do this.
I have a class template that inherits from a class that is a template
parameter. This base class tells the templated class where an array
is located. I want both the array and the instance of an
instantiation of this template to be data members of the same class.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
- Next message: JKop: "Re: How can I achieve this behaviour?"
- Previous message: Kai-Uwe Bux: "Re: Is C++ fundamentally broken?:was:Re: C++ unit testing"
- In reply to: Matthew Hall: "Re: pushing the limits of use-before-declaration within a class"
- Next in thread: Conrad Weyns: "Re: pushing the limits of use-before-declaration within a class"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|