Sign in to follow this  

Can this be done in C++?

This topic is 4356 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone. Say I've got a template which holds a user defined type (probably a class for a game object). And I want to create an interface (using overloaded operators) for the developer to access the copy of the class in the template more easily IE: Object<Player> P1; P1->Draw(); basically, can I have a overload like this that points to a function of a member class of the template class? (sounds awkward to ask not sure if im wording that right). Does this can be done by function pointers? like, for the operator overloading paramers, could put a pointer to the function to be used? If it cant be done its no major problem, there are other ways around it. And if you dont udnerstand me/im wording it badly, please let me know so i can try to post a better explanation of what im trying to do.

Share this post


Link to post
Share on other sites
If I understand you correctly, you can overload operator -> to achieve what you want. For example:


template <class T>
class Object
{
public:
// ... whatever else you want in the interface

T* operator-> () { return &mInstance; }
const T* operator-> () const { return &mInstance; }

private:
T mInstance;
};

Share this post


Link to post
Share on other sites
I don't think I follow. Is Draw() a public method of Player? You can accomplish that with an overloaded -> operator as follows:


template< typename T_ >
class Object
{
public:
T_* operator->(void) { return &mWrapped; }

private:
T_ mWrapped;
};




This would give you indirectly call any public method of T_. Are you looking for a more restrictive mechanism, or something altogether different (as I mentioned above I'm not sure I'm understanding you correctly)?

EDIT:
I was beaten! But I'll expand: what I meant by "more restrictive" was something like, you only want to be able to call a subset of T_'s public methods through Object. For example, Draw() and Update(), but not Destroy(), or something. In that case you could do something like:


template< typename T_ >
class Object
{
public:
void Draw(void) { mWrapped->Draw(); }
void Update(void) { mWrapped->Update(); }

// no implementation of Destroy(), you cannot call T_::Destroy()
private:
T_ mWrapped;
};



Attempting to create Object< T_ > for a T_ that doesn't have the appropriate methods will then fail to compile, providing automatic error checking. I'm not 100% convinced of the utility of this technique, but since you've provided no context...

Share this post


Link to post
Share on other sites
Currently, the functions themselves don't exist exactly, we're still planning this all. Still sort of debating whether we're going to use templates or just simply subclass all our objects.

I'll try to explain:

The template is of course initiated like Object<Type> foo;

Inside the template class is a copy of Type as it were.

We want an operator that can talk to Type directly through foo.

For instance, if the copy of Type is called "blah" in the object, we COULD access members of that class by going foo.blah.member_function();

But we want to be able to skip that and just put foo->member_function(); (or some other operator, doesn't really matter but -> makes sense).

Know what I mean? It's pretty much for convenience, to give it the feel of a class even though its contained inside a template (which allows us to make the overall game procedure simpler)

Edit::

And to D00fus, thanks I'll try that right now, I think that will work.

Share this post


Link to post
Share on other sites
Yeah jpetrie is right, if you want any restrictions on what parts of the wrapped type's interface you can access then the approach I gave isn't sufficient. Another option if you do eventually want that functionality is to return a proxy object from operator-> that restricts the interface appropriately, but like jpetrie I'm not sure of why you'd want to do this without the context :)

Share this post


Link to post
Share on other sites
Some solutions: (I realize that in the time it's taken me to write these, other solutions will have been submitted..)


The easy solution would be:

template <class T>
class Object {
public:
T m_t;
void Draw() { m_t.Draw(); }
};

class Player {
public:
void Draw() { printf ("Drawing\r\n"); }
}; int i;

...
Object<Player> P1;
P1.Draw();




A variation of the example above would be one using inheritance to ensure our Object and Player classes have the same interface. Deriving Object from IDrawable is optional, of course; I did it simply to ensure Object had the same interface as any IDrawable classes, which neatens it a bit imho.


class IDrawable {
public:
virtual ~IDrawable(){}
virtual void Draw()=0;
};

class Player : public IDrawable {
public:
virtual void Draw() { printf ("Drawing\r\n"); }
};

template <class T>
class Object : public IDrawable {
public:
T m_t;
virtual void Draw() { m_t.Draw(); }
};

...

Object<Player> P1;
P1.Draw();



Yet another option would be to derive your Object class from it's template parameter. Of course, the IDrawable interface is completely optional, but I like it.


class IDrawable {
public:
virtual ~IDrawable() {}
virtual void Draw() = 0;
};

class Player : public IDrawable {
public:
virtual ~Player() {}
virtual void Draw() { printf ("Drawing\r\n"); }
};

template <class T>
class Object : public T {
};

...

Object<Player> P1;
P1.Draw();



If you want to specify the Player function to call in the template, you can do something like this, where we pass the function pointer as part of the template specification:


template <class T, void(T::*DrawFunc)()>
class Object {
public:
T m_t;
void Draw() { (m_t.*DrawFunc)(); }
};

class Player {
public:
void Draw() { printf ("Drawing\r\n"); }
}; int i;

...

Object<Player, Player::Draw> P1;
P1.Draw();




There are probably other solutions, but there are a few.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hmmm I just want to know what was meant by "restrictions" ? because the private/public rules and what not still apply, probably not protected since no subclassing is actually taking place (or does it apply to templates as well) ?

I just want to know what was meant by restrictions. Currently for testing purposes, the solution by doofus has worked fine.

Share this post


Link to post
Share on other sites
Hi again. I've just realized an issue with this:

if the template instance is a pointer? Then it gets confused and says it can't find the members of the type's class in the template class (because yeah they aren't there). Obviously we will need to have pointer functionality with these object classes...

Is it likely that it's simply getting confused because pointers would always use the -> operator regardless of overloading?

Share this post


Link to post
Share on other sites
@anonymous:

What I and I assume jpetrie were meaning by restrictions was if the OP for some reason wanted to restrict which parts of the public interface could be accessed - allow only the Draw member function to be called for example.

@AAAP:

This is because in this case if T is already a pointer type, say X*, then the return value from operator-> is X** (ie T*) which is invalid. To get around this, you could use template techniques to make sure the return value is a pointer. You could do this with Boost more reliably, but you could try implementing it something like this:


template <typename T>
struct make_pointer
{
typedef T* ptr;
typedef const T* const_ptr;

static ptr get_pointer(T& t) { return &t; }
static const_ptr get_pointer(const T& t) { return &t; }
};

template <typename T>
struct make_pointer<T*>
{
typedef T* ptr;
typedef const T* const_ptr;

static ptr get_pointer(T* t) { return t; }
static const_ptr get_pointer(const T* t) { return t; }
};

template <typename T>
class Object
{
public:
// ... blah ...

typename make_pointer<T>::ptr operator-> () { return make_pointer<T>::get_pointer(mInstance); }
typename make_pointer<T>::const_ptr operator-> () const { return make_pointer<T>::get_pointer(mInstance); }

private:
T mInstance;
};




I haven't tried compiling this but the technique should be valid. This should let you store either an instance or a pointer to an instance in Object and have both work interchangeably. There could well be a better way of doing it. Again though I'm not sure exactly what all this gets you :)

[edit - fixed one obvious typo]

Share this post


Link to post
Share on other sites

This topic is 4356 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this