By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,948 Members | 1,215 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,948 IT Pros & Developers. It's quick & easy.

pushing the limits of use-before-declaration within a class

P: n/a
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;

};

#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?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
wk****@yahoo.com (Walt Karas) writes:
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;

};

#include <stdio.h>

int main(void)
{
A a;

a.c.set();

// Should print 10.
printf("%d\n", a.i);

return(0);
} [...] 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?

struct A {

struct C {
friend class A;
void set() { a.i = 10; }
private:
C(A& anA): a(anA) {}
A& a;
};

A(): c(*this) {}

C c;
int i;
};

HTH.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #2

P: n/a
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.

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){}
};

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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #3

P: n/a

"Walt Karas" <wk****@yahoo.com> wrote in message
news:c6**************************@posting.google.c om...
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;

};

#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?

struct A
{
int i;

struct C
{
A& owner;

C(A& i_Owner) :
owner(i_Owner)
{
}
void set()
{
owner.i = 10;
}

} c;

A() : c(*this) {}
};

Regards,
Conrad Weyns
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #4

P: n/a

"Matthew Hall" <ma****@math.uiuc.edu> wrote in message
news:ch**********@news.ks.uiuc.edu...
Walt Karas wrote: [...]
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){}
};

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
Hi,
I practiced this friendship for years, but I was recently put right in a
thread on comp.std.c++.
The threads subject was "Private Methodes declared outside of the class"
Evidently, the friend declaration is a misconseption. Here is an snippet
from Jim Hyslop's respons:
Recapping the code in question:
> class A
> {
> private:
> int x;
>
> class Impl;
> friend class Impl;


It is not possible to write a well-formed declaration that allows
A::Impl access to A's private members. 11.4 para 1 states "A friend of a
class is a function or class that is not a member of the class ...."
Impl *is* a member of A, therefore A cannot grant it friendship.

Obviously, that's a mistake in the standard. Some compilers get around
the mistake by allowing the friend declaration, some get around it by
implicitly declaring nested classes friends.

DR 45 addresses this by allowing Impl access to all members to which A
has access (this has the effect of making friendship transitive).


The following appears to be well formed and accepted by msvc 7.1, mwcw 9.2
and online Comeau:

class A
{
private:
int x;

class B
{
A& a;

public:
B(A& _a) : a(_a) {}

void setX(int _x) { a.x = _x; }
} b;

public:
A() : b(*this) {}
void setX(int _x) { b.setX(_x); }
};

B can access everything in its parent class A without friendship.
Regards,
Conrad Weyns

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #5

P: n/a
Matthew Hall <ma****@math.uiuc.edu> wrote in message news:<ch**********@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! ]
Jul 22 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.