![]() |
| [[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]] |
|
|
#1 |
|
DevMaster Staff
Join Date: Sep 2003
Location: Hell
Posts: 1,109
|
Hello again,
Here's the situation. Imagine you had a callback function that takes 4 arguments. x,y position of your mouse pointer, a bool indicating if a button is pressed, and then an int indicating the button that is pressed. Now imagine you already have a function that takes 2 ints representing the mouse coordinates and then draws a sprite at those coordinates. You can't assign this function to the callback because the sigs don't match. I had this situation a while back and I didn't feel like writing a whole new function to take into account the extra bool and int that I really had no car for at the time. So I wrote up an argument caster. What it does, it takes a function object and casts it to another function object that must have the same return type, but can have a different number of parameters. something like: Code:
I've made args_cast so that you can also rewire the arguments. So if you wanted the 4th parameter to go to the 1st parameter of the actual function, you could do: callback = args_cast< 2, bool(int,int,bool,int), 4 > or if you wanted the 3rd and 4th of the synthesized function to go to the 1st and 2nd of the actual function: callback = args_cast< 2, bool(int,int,bool,int), 3, 4 > The first template parameter is a number indicating how many arguments the actual function takes. So here's the args_Cast implementation. My current implementation allows a maximum of a 5 argument synthesized function. (synthsized function being the one that takes dummy arguments) NOTE: you need to have boost installed as I make use of the function_traits template that allows for syntax such as some_func<bool(int,int)> as opposed to some_func<bool, int, int>. There's also a lot of "mechanical code" involved in this implementation, a job for boost.preprocessor I'm sure. Also, I'm thinking of submitting this to boost, what do you guys think? Code:
|
|
|
|
|
|
#2 |
|
Senior Member
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
|
I'm not sure. I personally wouldnt use it because it has a confusing syntax.
The reason I think its confusing is because its not obivous what parameters get mapped/discarded. If you want an example of a move obivious way of mapping look at boost bind. Perhaps you could extend bind to have a way of discarding arguments. However in that sort of case, I'd prefer adding callback function which explicitly maps the the callback. Theres no extra dependencies and it compiles tonnes faster. Whats a more natural c++ syntax this: args_cast< 2, bool(int,int,bool,int), 3, 4 >(&drawfunc) or this: calbackdrawfunc(int x, int y, bool u, int z) { return drawfunc(u,z); } ? Last edited by dave_ : 11-25-2006 at 08:26 AM. |
|
|
|
|
|
#3 |
|
Valued Member
Join Date: May 2003
Location: Canada
Posts: 111
|
I just use boost::any:
typedef std::vector<boost::any>ParameterListType; typedef boost::any ParameterType; typedef void (ICallable::*FunctionPtrType)(ParameterListType& params); Like so: Code:
___________________________________________
http://stodge.blogspot.com |
|
|
|
|
|
#4 |
|
DevMaster Staff
Join Date: Sep 2003
Location: Hell
Posts: 1,109
|
dave_:
The syntax would be documented of course, so I don't think it would be any more complicated then using something like bind. First parameter is the number of args that the real function takes. Second parameter is the signature of the synthesized function and what follows are rewiring parameters which are not necessary. By default the parameters are mapped according to how they appear in the sythesized function. So if the synthesized function has 4 args and the real function has 3 args, by default, the first 3 args to the synthesized function are passed to the real function. The rewiring parameters that follow the sythesized function signature parameter are just like boost.bind, except thay're not placeholders but integers specifying which argument of the synthesied function will be directed to "this" location of the real function. As for adding an explicit callback that calles the real funciton, well of course that's a solution but the args_cast was made to avoid cluttering with those types of functions unnecessarily, it should enhance readability as well. What kind of syntax would you see with something like this. About extending bind: I don't think that should be done because bind has a specific purpose: it binds arguments to functions. args_cast has a specific purpose: expand the number of arguments a function can take, while discarding the extra ones. As it is bind cannot be made to expand functions, and doing so would kid of give it another purpose which i think should be made seperate (like with the args_cast) stodge: while that way works of course, it involves too much boiler-plate code on the client side, which is something I try to avoid. I wouldn't want someone making a callback to follow too many protocols, give them more flexibility. I'd rather have clients follow less strict protocols. The function signature is the main protocol with a callback, args_cast makes following that less strict. |
|
|
|
|
|
#5 |
|
Valued Member
Join Date: May 2003
Location: Canada
Posts: 111
|
Too much boiler plate code? I don't understand what you mean. Also, how is this not flexible? I give the developer the ability to store whatever they want into the parameter list.
___________________________________________
http://stodge.blogspot.com |
|
|
|
|
|
#6 | |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Quote:
Code:
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. Last edited by .oisyn : 11-26-2006 at 09:48 AM. |
|
|
|
|
|
|
#7 |
|
Senior Member
Join Date: Sep 2005
Location: Hamburg / Germany
Posts: 597
|
Hm. to me it looks like this code solves a problem that should not exist.
|
|
|
|
|
|
#8 |
|
Valued Member
Join Date: May 2003
Location: Canada
Posts: 111
|
Ah I see, that's why I do this:
Timer* timer= HB_GET_PARAMETER(params, Timer*, 0); With a similar macro to push parameters. I know it's not to everyone's taste but I quite like this. ![]()
___________________________________________
http://stodge.blogspot.com |
|
|
|
|
|
#9 |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
How would that macro handle the conversions in my example? It can't, and that makes it a hassle to work with.
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
|
|
|
|
|
#10 | ||
|
DevMaster Staff
Join Date: Sep 2003
Location: Hell
Posts: 1,109
|
Quote:
oh i didn't mean your code in not flexible, it just has too many "rules" you need to follow. I meant giving the client more flexibility with those rules. Cause that is what args_cast is supposed to do. Quote:
Yeah I guess... but in todays work envionments where you're using code passed down through God only knows how many hands, you could come across a callback with a specific sig, and a function that can handle your situation that has a different signature. And suppose you change the signature to match, then you may have to change all invocations of said function. Or you can wrap the function in another object (as dave_ showed), but that produces clutter, or you can cast it.. but that adds to compile time. At the end you have multiple solutions with their own advantages/disadvantages. |
||
|
|
|
|
|
#11 | |
|
Member
Join Date: Sep 2005
Posts: 51
|
Quote:
Writing a temporary function would have taken you a minute. Your function-caster looks so complicated, i bet you have had fun developing it more than a day. I wouldn't wonna work with such code. Nobody, except you, knows what's going on. The most straight-forward solution is short, clear, typesafe and every c++ noob can understand it and see what's the problem in the first place. But that's just my opinion. Jan. |
|
|
|
|
|
|
#12 |
|
Valued Member
Join Date: May 2003
Location: Canada
Posts: 111
|
Code:
Gives: Code:
Which I *think* is what you're implying. Correct me if I'm not understanding your example fully.
___________________________________________
http://stodge.blogspot.com |
|
|
|
|
|
#13 |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Jesus why must you make your example so complex
![]() I'll strip it down to the bare essentials: Code:
Code:
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
|
|
|
|
|
#14 |
|
Valued Member
Join Date: Aug 2005
Location: Seoul
Posts: 272
|
nice, but slightly over-engineered..
![]() |
|
|
|
|
|
#15 |
|
DevMaster Staff
Join Date: Sep 2003
Location: Hell
Posts: 1,109
|
It actually didnt take more then a few hours to develop (and that also because of the repetative typing). It's just that it has a lot of mechanical code that's why it looks complex, but if you strip it down to it's basic structures it's not really complex at all. It uses some very simple template tricks, but because of the repetativeness it looks bloated. If I wrote the templates with boost.preprocessor it's probably be like 50 lines long or something max.
As for no-one but me knowing: most of the boost libraries are the same, everyone's using those though. btw: args_cast also works wonders with lambda (because of it's placeholder limitation) , especially when writing lambda functions for callbacks. But your opinion is your opinion ![]() |
|
|
|
|
|
#16 | |
|
Valued Member
Join Date: Aug 2005
Posts: 162
|
Quote:
Actually, "everyone" is not using boost. I stay away as much as possible, and most of the people I work with does too. |
|
|
|
|
|
|
#17 | |
|
Senior Member
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
|
Quote:
Good thing the C++ standards board aren't like you! |
|
|
|
|
|
|
#18 | |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Quote:
As I said before, every self-respectable C++ programmer has boost installed. What that implies is up to you ![]()
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. Last edited by .oisyn : 12-01-2006 at 04:23 AM. |
|
|
|
|
|
|
#19 | |
|
Valued Member
Join Date: Aug 2005
Location: Seoul
Posts: 272
|
Quote:
I don't. Unless the Boost-libraries become part the official standard, I don't see how to justify their use in the real production environments. I respect Boost-project and all the people involved, that they try to develop C++ further as a language by establishing new coding practises and technologies, but it's still a moving field and so there are some problems involved. For a homegrown project it might be fun to try out new technologies and all cool trickeries, but the priorities are considerably different in professional projects, where you actually have to deliver quality results and be able to share your code with other team members. Locking down an imporant project to some certain version of Boost would be needed in order to avoid regression bugs, but in the long run that would generate more problems than it solves. It's still a research project and existing practises and code conventions are bound to change - also not all people are familiar with __third__-party template libraries and things like code simplicity and easy (long-term) maintenance are of utmost importance. Somehow I feel Boost in some parts, and the function argument caster in question, have answers for problems, which shouldn't even exists in the first place. There are many who think themselves as hardcore C++ programmers and are using all kind of short-hand notations and "cool" tricks and thinking it's that what makes them good programmers - but are they really? Since when programming became an obfuscation contest? |
|
|
|
|
|
|
#20 | ||
|
DevMaster Staff
Join Date: Sep 2003
Location: Hell
Posts: 1,109
|
Quote:
If you restrict yourself to only the standard when it comes to c++ and are afraid of version lockdown then you're pretty screwed in a "real" production environment. Quote:
well we are dealing with c++ here ![]() c++ as a language has quite a few problems. boost is there because of those problems. as for your other question, of course being a "hardcore" c++ user doesnt make you a good programmer... but what's your point? That efforst like boost are not significant? Last edited by bladder : 12-02-2006 at 06:12 AM. |
||
|
|
|
|
|
#21 | |||
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Quote:
Quote:
Quote:
. The point was that the code was unreadable, but I don't understand why you need to be reading the code in the first place - it's the interface documentation that counts. You (and I don't mean _you_ but merely people in general) probably won't be reading your vendor's implementation of std::map either, nor the streambuf implementation that's responsible for writing to stdout, yet you're using it anyway.
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
|||
|
|
|
|
|
#22 |
|
Senior Member
Join Date: Sep 2005
Location: Hamburg / Germany
Posts: 597
|
Hm.. my thoughs about boost:
A nice and handy tool to do things fast, but there are problems involved when you write code for other people: You force them into a library which they don't nessesarily know. And you can hardly do a code coverage analysis anymore. Or better said: You can of cause run the analysis, but you'll never get close to 80% coverage. That might be not a problem for games, but for other fields it is. |
|
|
|
|
|
#23 |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
That counts for any library, even the standard C++ library.
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
|
|
|
|
|
#24 | ||
|
Valued Member
Join Date: Aug 2005
Location: Seoul
Posts: 272
|
Quote:
Yeah I'm aware of that, and hence said *until* they become part of the standard. Being part of the standard is important, as it greatly reduces problems associated with the version lockdown, compatibility issues and integration costs. People are more likely to get educated to use and know the standard library than third party solutions. This doesn't mean I don't respect Boost or other template-based framework projects. I do appreciate them a lot and I think they're changing the way we are looking at C++ as a language. There are lots of useful things in Boost and admittedly if didn't need to share code with lots of people(with varying skill levels) I would be more positive about it. That said, however, I would rather see some features of Boost incorporated in the language itself, such as anonymous functions(vs Boost Lambda). Quote:
|
||
|
|
|
|
|
#25 |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Actually I think we totally agree with eachother
![]()
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
|
|
|
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
|