Jump to content
  • Advertisement
Sign in to follow this  
deffer

Passing parameter of not specified type

This topic is 4872 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. I'm making event/scripting system for my engine. The event class, that I'm using, can have some parameters. As there are possibly many events, different parameters are required. There is really no problem reckognizing what type the parameter is for a certain event, both creating/passing and receiving/handling event with the parameter(s), as event knows what kind it is. So at first there was an additional void* member in the class, and user could pass any pointer, or value, by casting. I felt this is bad for two reasons: - it's ugly, and I'm aware that I could do this only because of my C background. - I cannot pass eg. 8-byte object by value, I have to alloc: new Value(v). It's bad for both performance reasons, and that it the block has to be explicitly deleted somewhere, which gives me less flexibility in designing the event handling flow/order. So I'm thinking: instead of void*, let's use something like:
template<int NMaxSize>
class CValPasserN
{
   char  m_Data[NMaxSize];
public:
   CValPasserN(void) {};
public:
   template<typename T>
   CValPasserN(const T& t)
   {
      STATIC_ASSERT(size_of_T_cannot_be_greater_than_N_Bytes, sizeof(T) <= NMaxSize);

      // Explicit cast to void*.
      memcpy(m_Data, reinterpret_cast<void*>(&t), sizeof(T));
   };
   template<typename T>
   operator T&()
   {
      STATIC_ASSERT(size_of_T_cannot_be_greater_than_N_Bytes, sizeof(T) <= NMaxSize);

      return *(reinterpret_cast<T*>(m_Data));
   };
};


as CValPasserN<12>, for example. It's still somewhat dirty and doesn't work with classes with virtual methods. In practice, it should only be used with POD-types. But still, it's wrapped and ready to go. What do you think? Does this make sense? /def

Share this post


Link to post
Share on other sites
Advertisement
This is rather dangerous, mostly because you destroy type safety: you can store a object of class A in your container, and restore an object of class B without any complain from the compiler. Setting the type as a template parameter for the whole class won't solve anything - using CValPasserN<A> instead of A? You'll still have some cast somewhere...
The problem is that you want to enforce type safety but you don't want to enforce it (ie, you want to be sure you operate on type T but at the same time if you do this you won't be able to have generic code that will operate on any kind of object). The solution to your problem will not be easy... :)

Regards,

Share this post


Link to post
Share on other sites
If you have many different kinds of events, that sounds to me like a call for inheritence. Rather than one event class that handles all possible parameters, you should have a base event class and derive specific event types from the base.

Share this post


Link to post
Share on other sites
My approach to a similar problem was just to pass everything as a string, and ensure that I can serialise any useful type to and from a string. If you're worried about performance at the event/scripting engine level though then I think it might be worth re-thinking your design. Alternatively you may be worrying about nothing.

You might want to look at boost::any also.

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
You'll still have some cast somewhere...
The problem is that you want to enforce type safety but you don't want to enforce it (ie, you want to be sure you operate on type T but at the same time if you do this you won't be able to have generic code that will operate on any kind of object).


No, I'm aware that I would loose type safety here. And I'm not crying.

Quote:
Original post by Emmanuel Deloget
You'll still have some cast somewhere...

That's my goal - eliminate casting at all(actually, hide it somewhere), make the code more cleaner.
Is there some less tricky solution?

I think I cannot templatize Event class, as all events must have same base interface(derived from one class)...
/def

Share this post


Link to post
Share on other sites
If you're using inheritance, you can use dynamic_cast. If the cast was sucessful it will give you a pointer to the requested type, otherwise it will give you a null pointer (easy to check to see if it was successful).

However, I'm not a huge fan of dynamic_cast - there are often better ways to get something done. I'd tend to agree with Kylotan to use a string.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dave Hunt
If you have many different kinds of events, that sounds to me like a call for inheritence. Rather than one event class that handles all possible parameters, you should have a base event class and derive specific event types from the base.


I already have a hierarchy of events, so I cannot create a second in paralel, at least not without RTTI :(

Quote:
Original post by Kylotan
My approach to a similar problem was just to pass everything as a string, and ensure that I can serialise any useful type to and from a string.


It's an alternative to RTTI, as the my data need not to be coded and parsed, so the only benefit would be in type-checking. And this is a run-time check, it's not so safe either, is it? Maybe it is...

Quote:
Original post by Kylotan
If you're worried about performance at the event/scripting engine level though then I think it might be worth re-thinking your design.


It may come to that, but let's not assume the worst yet ;)

Quote:
Original post by Kylotan
Alternatively you may be worrying about nothing.

Juicy idea, but I suppose it leads to increasing laziness, ending on the Dark Side

Share this post


Link to post
Share on other sites
And about using string for determining type: it's not that I don't know what type is the argument in event being processed. The event has it's kind, which allows me to choose proper handler.
Isn't it the same as keeping the arg type explicitly?

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Quote:
Original post by Dave Hunt
If you have many different kinds of events, that sounds to me like a call for inheritence. Rather than one event class that handles all possible parameters, you should have a base event class and derive specific event types from the base.


I already have a hierarchy of events, so I cannot create a second in paralel, at least not without RTTI :(


Ok. Obviously I don't have a clear picture of your problem. I think I'll bow out and see if I understand it better as the discussion continues.

Share this post


Link to post
Share on other sites
I'm not sure exactly of what you are trying to do, but I think this could help.

Have you thought about replacing the function that takes a void* with one that takes one of your event types and then overloading it for each event type. Then have a private function that takes the void* and the overloaded functions just call the void one. This way only your event types can be passed in, and only you do the casting to void*.

Hope it helps.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!