hi,
I would like to write some code where a C++ class (let's call it
Containee) which is a member variable of a Container class can call
methods in its Container class without holding a direct pointer to the
Container class:
#include <iostream>
class Containee
{
public:
Containee (int offset);
void Do (void);
private:
int m_offset;
};
class Container
{
public:
Container ();
void Do (void);
Containee m_containee;
private:
static int GetOffset (void);
};
Container::Container ()
: m_containee (GetOffset ())
{}
int
Container::GetOffset (void)
{
Container *self = 0;
Containee Container::* ptr = &Container::m_containee;
long containee = (long) &(self->*ptr);
return containee;
}
void
Container::Do (void)
{
std::cout << "Container::Do" << std::endl;
}
Containee::Containee (int offset)
: m_offset (offset)
{}
void
Containee::Do (void)
{
long self = (long)this;
long container = self-m_offset;
Container *containerPtr = reinterpret_cast<Container *> (container);
containerPtr->Do ();
}
int main (int argc, char *argv[])
{
Container container;
container.m_containee.Do ();
return 0;
}
The code above actually compiles, runs, and prints the expected output
but is not quite what I really want. What I want is to avoid to store the=
offset as a member in my Containee class and to make it a template non-
type argument. i.e., something like this:
template <long OFFSET>
class Containee
{
public:
void Do (void) {
long self = (long)this;
long container = self-OFFSET;
Container *containerPtr = (Container *) (container;
containerPtr->Do ();
}
};
However, I have not yet been able to figure out how to calculate the
offset and feed it to this Containee class template. I tried the
following:
#include <iostream>
class Base
{};
template <typename T, typename U, U T::*MEMBER_PTR>
class Containee : public Base
{
public:
void Do (void);
};
class Container
{
public:
void Do (void);
Containee<Container,Base,&Container::m_containee> m_containee;
private:
};
void
Container::Do (void)
{
std::cout << "Container::Do" << std::endl;
}
template <typename T, typename U, U T::*MEMBER_PTR>
void
Containee<T,U,MEMBER_PTR>::Do (void)
{
T *tmpContainer = 0;
long offset = (long)&(tmpContainer->*MEMBER_PTR);
long self = (long)this;
long container = self-offset;
Container *containerPtr = (Container *) (container);
containerPtr->Do ();
}
int main (int argc, char *argv[])
{
Container container;
container.m_containee.Do ();
return 0;
}
But that just does not work with my version of g++ (4.1.3):
test.cc:19: error: incomplete type =E2=80=98Container=E2=80=99 used in ne=
sted name
specifier
test.cc:19: error: template argument 3 is invalid
test.cc: In function =E2=80=98int main(int, char**)=E2=80=99:
test.cc:46: error: request for member =E2=80=98Do=E2=80=99 in
=E2=80=98container.Container::m_containee=E2=80=99, which is of non-class=
type =E2=80=98int=E2=80=99
Which somewhat does not surprise me very much: g++ wants to know the type=
of Container. To do this, it needs the type of m_containee which itself
needs the type of Container... And, I really dislike the syntax I had to
use for the Containee<> instance declaration.
So, would anyone have an idea on how I could hack this together ? I know
that what I am doing here is especially evil but, I can't refrain myself
from doing it: it does make me feel a little bit warm inside.
Mathieu
--
[ See http://www.gotw.ca/resources/clcm.htm
for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


|