Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411573 Posts in 69386 Topics- by 58444 Members - Latest Member: darkcitien

May 04, 2024, 01:05:28 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Technical Q&A
Pages: [1]
Print
Author Topic: Technical Q&A  (Read 1204 times)
Kadoba
Level 3
***



View Profile
« on: March 09, 2010, 02:44:15 PM »

I've come across lots of little technical problems before and have felt the impulse to create a new topic, but I thought they just didn't warrant their own thread.

So post your technical questions here if you don't want to start a new thread. Remember to be specific and if it's about programming try and include code to showcase your problem.


Ok, so I have this syntax in c++ to pass a function:

Code:
TestClass c;
Event e;
e.AddCallback<TestClass, &TestClass::TestFunction>(c);

// This is what the declaration of AddCallback looks like
template<class TObject, void (TObject::*TMethod)(int)>
void Event::AddCallback(TObject& argObj){};

This actually works but is there any way to be able to remove the reference operator(&) from the passed function in Event::AddCallback? I know it seems picky but I want to have the syntax as clean and simple as possible, and I really don't like passing pointers. I'd rather pass a reference and then get the pointer from within the function. And yes I realize I'm messing with raw pointers and not using const but I'm just trying to get it to work for the moment.

So the call will look like
e.AddCallback<TestClass, TestClass::TestFunction>(c);
Or possibly shorter/cleaner if possible.

And my second question is how would you go about making a unique id generator that can't overflow? Right now I just have unsigned longs that increment but values are never freed even when an object is destroyed. Even though longs have about 18 quintillion possible values there's still the improbable chance of an overflow. I was thinking about having each id be reusable but have a timestamp of when the last instance with that id died. Checks using the id with an older timestamps are invalidated. But then I realized there's the possibility of the timestamp overflowing... So yeah obviously I'm not use to lower level programming.
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #1 on: March 09, 2010, 06:07:08 PM »

I've come across lots of little technical problems before and have felt the impulse to create a new topic, but I thought they just didn't warrant their own thread.

So post your technical questions here if you don't want to start a new thread. Remember to be specific and if it's about programming try and include code to showcase your problem.


Ok, so I have this syntax in c++ to pass a function:

Code:
TestClass c;
Event e;
e.AddCallback<TestClass, &TestClass::TestFunction>(c);

// This is what the declaration of AddCallback looks like
template<class TObject, void (TObject::*TMethod)(int)>
void Event::AddCallback(TObject& argObj){};

This actually works but is there any way to be able to remove the reference operator(&) from the passed function in Event::AddCallback? I know it seems picky but I want to have the syntax as clean and simple as possible, and I really don't like passing pointers. I'd rather pass a reference and then get the pointer from within the function. And yes I realize I'm messing with raw pointers and not using const but I'm just trying to get it to work for the moment.

So the call will look like
e.AddCallback<TestClass, TestClass::TestFunction>(c);
Or possibly shorter/cleaner if possible.

The & is required for pointers to (non-static) member functions.  I don't think there's any way around that.  Normal functions do not require the &, mostly for C compatibility.

Quote
And my second question is how would you go about making a unique id generator that can't overflow? Right now I just have unsigned longs that increment but values are never freed even when an object is destroyed. Even though longs have about 18 quintillion possible values there's still the improbable chance of an overflow. I was thinking about having each id be reusable but have a timestamp of when the last instance with that id died. Checks using the id with an older timestamps are invalidated. But then I realized there's the possibility of the timestamp overflowing... So yeah obviously I'm not use to lower level programming.

I store IDs in a map, and just remove them from the map after they're released.  Every time I need a new ID I iterate through the map and return the lowest unused value.  This works fine for me, here's the code I use:

Code:
SoundID NextSoundID() throw (Exhausted)
{
    // Check to see if all SoundIDs have been claimed.
    if (sound_list.size() == numeric_limits<SoundID>::max() - 1)
    {
        throw Exhausted("ASBase::SoundID", NULL, "NextSoundID");
    }

    // Assume it's 1.
    SoundID next = 1;
       
    for (map<SoundID, Sound*>::const_iterator i = sound_list.begin(); i != sound_list.end(); ++i)
    {
        // If this number is not taken, return it.
        if (i->first != next)
        {
             return next;
        }
           
        // Look for the next number.
        next++;
    }
       
    return next;
}

SoundID is a typedef over unsigned int, and 0 is reserved as a "null" SoundID.
« Last Edit: March 09, 2010, 06:12:24 PM by Average Software » Logged



What would John Carmack do?
Toeofdoom
Level 2
**



View Profile WWW
« Reply #2 on: March 09, 2010, 09:17:09 PM »

For the ID part, it kinda depends what you need the IDs for. For example C++ already includes unique IDs that are guaranteed not to overflow (or if they do, you're kinda screwed anyway). They're pointers. For example when Ogre3D asks me for a unique mesh ID, my current solution is to just stick the pointer to the object it represents into a stringstream. It sometimes seems odd, but it works perfectly fine.

Code:
b2Fixture* mFixture;

...

std::stringstream ss;
ss << "F_" << mFixture; //Use the fixture pointer as a unique identifier, because it needs a unique name with ogre.
//If 2 fixtures end up with the same address somehow, it will die anyway.

mEntity = OgreFramework::getSingletonPtr()->m_pSceneMgr->createEntity(ss.str(), meshName);

Of course in this case I need to be careful to get rid of the Entity when the fixture disappears, but if I didn't do that I would have a memory leak anyway.
Logged

Kadoba
Level 3
***



View Profile
« Reply #3 on: March 10, 2010, 01:59:37 AM »

@AverageSoftware
Ok, well at least I know I have no alternative with the function pointers. If I was really desperate I could make a macro but typing the & wont kill me. And what do you mean "normal" functions?  Also, what I'm paranoid about with IDs is that another object will store it and try to use it later after it is destroyed. But actually, the more I think about it, the more I have have trouble thinking of a valid reason for custom IDs in the first place. I guess my view of them are kind of skewered because I come from Game Maker and IDs are basically used as pointers.

@ToeofDoom
Yeah I get what you mean. The only advantages I can think of that custom ids have over pointers are human readability and serialization. Neither are really important to me right now.

Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #4 on: March 10, 2010, 05:51:27 AM »

@AverageSoftware
Ok, well at least I know I have no alternative with the function pointers. If I was really desperate I could make a macro but typing the & wont kill me. And what do you mean "normal" functions?

Functions that aren't members of classes.

Quote
Also, what I'm paranoid about with IDs is that another object will store it and try to use it later after it is destroyed.

That's a risk with almost anything you use, it's not particular to IDs.  One way around this is reference counting.
Logged



What would John Carmack do?
Dathgale
Level 0
**



View Profile WWW
« Reply #5 on: March 10, 2010, 08:06:29 AM »

Asking if you really need to type the & operator is kind of like asking if you really need to type the + operator to compute the sum of two integers. The answer is yes - but only if you want the computer to understand what you want it to do. Why is typing that character such a big deal, anyway?
Logged

Kadoba
Level 3
***



View Profile
« Reply #6 on: March 10, 2010, 01:58:30 PM »

Asking if you really need to type the & operator is kind of like asking if you really need to type the + operator to compute the sum of two integers. The answer is yes - but only if you want the computer to understand what you want it to do. Why is typing that character such a big deal, anyway?

It isn't. It's just a small nit-picky thing that I wanted to avoid if possible. I can't, and that's perfectly fine. If anything has to be referenced for a function I would normally always just pass an implicit reference. That way I don't have to remember which functions take pointers as parameters.

Also you don't have to type + to compute the sum of two integers.
« Last Edit: March 10, 2010, 02:04:28 PM by Kadoba » Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic