Referencing the container object

  • Thread starter Alessandro [AkiRoss] Re
  • Start date
A

Alessandro [AkiRoss] Re

Hello,
I'm in a situation where an object (class User), contained in another
object (class Container), need to get a reference to its container.

Here's a working code that does what I mean:

struct User {
template <typename C> User(C &cont) { /* ... */ }
};

struct Container {
User u, v, z;
Container(): u(*this), v(*this), z(*this) {}
};

My problem: I'd like to remove the X(*this), in some way.
In other words: when an User object is instantiated within the
Container class, it should get in some way a reference/pointer to the
Container instance.

I thought about using a method which return the address of the
Container instance, and passing it as template parameter, like this:

template <typename C, C &(C::*instance)()>
struct User {
User() {
C &c = ???->*instance();
}
};

struct Container {
Container &self() { return *this; }
User<Container, &Container::self> u;
};

But, of course, this doesn't work, because calling the instance()
pointer-to-method required an associated instance to work with, and
it's exactly what I'm trying to get :)

Why I'm doing this? Because in the Container class (or any subclass),
they may be a lot of User instances, and it's rather unpractical to
initialize them one by one in the constructor list.

How can I do this?
Thanks,
~Ale
 
A

Alf P. Steinbach

* Alessandro [AkiRoss] Re:
Hello,
I'm in a situation where an object (class User), contained in another
object (class Container), need to get a reference to its container.

Here's a working code that does what I mean:

struct User {
template <typename C> User(C &cont) { /* ... */ }
};

struct Container {
User u, v, z;
Container(): u(*this), v(*this), z(*this) {}
};
OK.


My problem: I'd like to remove the X(*this), in some way.
In other words: when an User object is instantiated within the
Container class, it should get in some way a reference/pointer to the
Container instance.

I thought about using a method which return the address of the
Container instance, and passing it as template parameter, like this:

template <typename C, C &(C::*instance)()>
struct User {
User() {
C &c = ???->*instance();
}
};

struct Container {
Container &self() { return *this; }
User<Container, &Container::self> u;
};

Confusion of compile time and run time.

But, of course, this doesn't work, because calling the instance()
pointer-to-method required an associated instance to work with, and
it's exactly what I'm trying to get :)

Why I'm doing this? Because in the Container class (or any subclass),
they may be a lot of User instances, and it's rather unpractical to
initialize them one by one in the constructor list.

Either design is bad, or you should be able to just iterate. E.g.

class Container;

class User
{
public:
User( Container& ) {}
};

class Container
{
private:
std::vector<User> myUsers;
public:
Container() : myUsers( 42, *this ) {} // 42 User instances.
};


How can I do this?

See above.


Cheers & hth.,

- Alf
 
A

Alessandro [AkiRoss] Re

* Alessandro [AkiRoss] Re:
Confusion of compile time and run time.

Yes, of course. I wrote it as a suggestion (in the case it could be
useful :D)
Either design is bad, or you should be able to just iterate.  E.g.

   class Container;

   class User
   {
   public:
       User( Container& ) {}
   };

   class Container
   {
   private:
       std::vector<User> myUsers;
   public:
       Container() : myUsers( 42, *this ) {}    // 42 User instances.
   };


See above.

Cheers & hth.,

- Alf

No, it shouldn't iterate.
Actually, the User objects are functors and need to be accessed with
the name specified by the user... E.g.

struct Functor { void operator()() { /* blah */ } }

struct UserContainer : public MyContainer {
Functor method;
} cont;

cont.method();

Too bad, I'm not an expert about design, but I'm trying to implement
this code to be usable by future programmers.
And well, functors used like these is pretty straightforward.

In addition, the functor must be registered in the container object...
If I don't find an automagic way of doing this, the user must do it,
and it's more error prone.

Thanks anyway :) I'll try to consider other approaches.
 
A

Alessandro [AkiRoss] Re

   private:
       std::vector<User> myUsers;

By the way, in my example it wasn't clear, but it must be: User isn't
just a class, it can be a set of classes:

struct Cont {
User1 u1;
User2 u2;
UserN uN;
};

and they may be (but shouldn't) unrelated in the hierarchy, so a
vector<User> or vector<Base> doesn't do.

Thanks!
 
A

Alf P. Steinbach

* Alessandro [AkiRoss] Re:
* Alessandro [AkiRoss] Re:
Confusion of compile time and run time.

Yes, of course. I wrote it as a suggestion (in the case it could be
useful :D)
Either design is bad, or you should be able to just iterate. E.g.

class Container;

class User
{
public:
User( Container& ) {}
};

class Container
{
private:
std::vector<User> myUsers;
public:
Container() : myUsers( 42, *this ) {} // 42 User instances.
};

See above.

Cheers & hth.,

- Alf

No, it shouldn't iterate.
Actually, the User objects are functors and need to be accessed with
the name specified by the user... E.g.

struct Functor { void operator()() { /* blah */ } }

struct UserContainer : public MyContainer {
Functor method;
} cont;

cont.method();

Too bad, I'm not an expert about design, but I'm trying to implement
this code to be usable by future programmers.

It's unclear what you're trying to do.

As is very common, it seems that you're focusing on an imagined (and unworkable)
technical solution to some problem that you haven't divulged.

I can make guesses based on experience.

One would be that whatever you're trying to achieve would be better done with
simple virtual routines,

struct UserContainer
{
virtual void method() ...
};

Another would be that whatever you're trying to achieve would be better done
with an explicit call syntax,

struct UserContainer
{
virtual void call( Functor& ... ) ...
};

But since my telepathic abilities have deteriorated somewhat in recent years,
it's difficult to say.

It would be simpler if you'd described what you're trying to achieve (and not
some invented generalization thereof).

And well, functors used like these is pretty straightforward.

In addition, the functor must be registered in the container object...
If I don't find an automagic way of doing this, the user must do it,
and it's more error prone.

Thanks anyway :) I'll try to consider other approaches.

Good idea.


Cheers & hth.,

- Alf
 
A

Alessandro [AkiRoss] Re

As is very common, it seems that you're focusing on an imagined (and unworkable)
technical solution to some problem that you haven't divulged.


Yes, imagined of course :) Trying "other approaches" means also trying
something that may be unexplored. If this method isn't workable, I'll
wont use it.

No, I've said everything apart specific stuff about what I'm doing:
all what I'm trying to get is the liberty for the subclasser to insert
functors in some object and having that functors to get automatically
the object's reference.
One would be that whatever you're trying to achieve would be better done with
simple virtual routines,

   struct UserContainer
   {
       virtual void method() ...
   };

Nope, because the functors are reusable and contains many other
informations. Putting them as standard methods doesn't fit.
Another would be that whatever you're trying to achieve would be better done
with an explicit call syntax,

   struct UserContainer
   {
       virtual void call( Functor& ... ) ...
   };

This would be better (and by the way, actually my code works exactly
like this :).
But since my telepathic abilities have deteriorated somewhat in recent years, it's difficult to say.
It would be simpler if you'd described what you're trying to achieve (and not some invented generalization thereof).

I'm trying to use functors objects as they would be methods in C++. (I
thought it was pretty clear in my first reply. Sorry)

There are many issues in trying to do this... For example, accessing
private members. That's why I always used struct and no class.
Because... It's easy: methods in C++ aren't objects, while functors
are.
Doing it with virtual methods as you wrote requires some work to the
user that I would like to eliminate.
For example, have to be instantiated:
Functor = functor(&userContainer);
have to be registered:
userContainer.register(functor);
has to be used:
userContainer.call(functor, params);

well, doing all this by hand is really boring, and wrong, because
"repetitive job is done by machines. If you're doing repetitive job,
you're doing it wrong" (cit. my C++ course teacher).

I would like to simulate the normal use of methods (and this was clear
from my example, wasn't it?)

struct MyObj { method_declaration } obj.
obj.use_as_normally(params); // Happy user :) Common way of doing
things = easy way of doing thins.

as you see, no need instantiate the method, no need of registering it,
no need of doing by hand all the things that I, implementer of the
library, could do with ease *one time*, removing this cumbersome job
from users' shoulders.

I'm not saying that this IS feasible in C++ or that this must be the
BEST way of doing it or that I MUST do it like this.
I _already did it_ "in a normal way", but it has flaws that I'd like
to remove. This is so far the best method I've found, and I'm trying
to get it done (if possible) in C++.

Your contribute is useful anyway, thanks.
~Ale
 
A

Alf P. Steinbach

* Alessandro [AkiRoss] Re:
Yes, imagined of course :) Trying "other approaches" means also trying
something that may be unexplored. If this method isn't workable, I'll
wont use it.

No, I've said everything apart specific stuff about what I'm doing:
all what I'm trying to get is the liberty for the subclasser to insert
functors in some object and having that functors to get automatically
the object's reference.


Nope, because the functors are reusable and contains many other
informations. Putting them as standard methods doesn't fit.


This would be better (and by the way, actually my code works exactly
like this :).


I'm trying to use functors objects as they would be methods in C++. (I
thought it was pretty clear in my first reply. Sorry)

There are many issues in trying to do this... For example, accessing
private members. That's why I always used struct and no class.
Because... It's easy: methods in C++ aren't objects, while functors
are.
Doing it with virtual methods as you wrote requires some work to the
user that I would like to eliminate.
For example, have to be instantiated:
Functor = functor(&userContainer);
have to be registered:
userContainer.register(functor);
has to be used:
userContainer.call(functor, params);

well, doing all this by hand is really boring, and wrong, because
"repetitive job is done by machines. If you're doing repetitive job,
you're doing it wrong" (cit. my C++ course teacher).

I would like to simulate the normal use of methods (and this was clear
from my example, wasn't it?)

struct MyObj { method_declaration } obj.
obj.use_as_normally(params); // Happy user :) Common way of doing
things = easy way of doing thins.

as you see, no need instantiate the method, no need of registering it,
no need of doing by hand all the things that I, implementer of the
library, could do with ease *one time*, removing this cumbersome job
from users' shoulders.

I'm not saying that this IS feasible in C++ or that this must be the
BEST way of doing it or that I MUST do it like this.
I _already did it_ "in a normal way", but it has flaws that I'd like
to remove. This is so far the best method I've found, and I'm trying
to get it done (if possible) in C++.

Your contribute is useful anyway, thanks.

Check out multiple inheritance. Make you "functors" base classes.

Cheers & hth.,

- Alf
 
A

Alessandro [AkiRoss] Re

Check out multiple inheritance. Make you "functors" base classes.

Meh, it requires to do something like this, or am I wrong?

struct Functor {
Functor fun1;
operator() //do something
};

struct Functor2 {
Functor2 fun2;
operator()
};

struct Container: public Functor, public Functor2 {} cont;

cont.fun1();
cont.fun2();

What if names collide? Container may be a

struct Container: public Parent {}

which (Parent) already have fun1(). How can I handle this?

Thanks!!
~Ale
 
A

Alf P. Steinbach

* Alessandro [AkiRoss] Re:
Meh, it requires to do something like this, or am I wrong?

struct Functor {
Functor fun1;
operator() //do something
};

struct Functor2 {
Functor2 fun2;
operator()
};

struct Container: public Functor, public Functor2 {} cont;

cont.fun1();
cont.fun2();

If you try to compile the above you'll see that there are errors both at the
syntax level and the semantics.

So it's unclear exactly what you mean. However, defining operator() in multiple
base classes is probably not helpful towards your earlier goal.

Please post only real code.

What if names collide? Container may be a

struct Container: public Parent {}

which (Parent) already have fun1(). How can I handle this?

How would you handle it for some other scheme?

Decide what the effect should be or whether it should be supported at all.

Techniques that may be relevant include virtual inheritance and
renaming-via-wrapper.


Cheers & hth.,

- Alf
 
A

Alessandro [AkiRoss] Re

* Alessandro [AkiRoss] Re:


Meh, it requires to do something like this, or am I wrong?
struct Functor {
  Functor fun1;
  operator() //do something
};
struct Functor2 {
  Functor2 fun2;
  operator()
};
struct Container: public Functor, public Functor2 {} cont;
cont.fun1();
cont.fun2();

If you try to compile the above you'll see that there are errors both at the
syntax level and the semantics.

So it's unclear exactly what you mean. However, defining operator() in multiple
base classes is probably not helpful towards your earlier goal.

Yes, sorry. It was totally idiotic. You're right.

The semantic was this:
struct Fun1 { fun1(); }
struct Fun2 { fun2(); }
struct Cont : public Fun1, Fun2 {} cont;

cont.fun1();
cont.fun2();

Mmh yes, multiple inheritance may do it, I need to study it a little
bit more...

Thanks! It helped!! :)

~Ale
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top