|
Liosan
|
 |
« Reply #2820 on: August 18, 2012, 04:41:45 AM » |
|
Created a 'chain_cast' operator in C++ this morning. Simply replaces a series of static_cast's so something like (...) The cool part was using boost preprocessor macros to create all the iterations.
I'm not sure what made more nervous, your problem or your solution... Liosan
|
|
|
|
|
Logged
|
|
|
|
|
Crimsontide
|
 |
« Reply #2821 on: August 18, 2012, 05:05:57 AM » |
|
Why would either make you nervous?
|
|
|
|
|
Logged
|
|
|
|
|
BorisTheBrave
|
 |
« Reply #2822 on: August 18, 2012, 05:32:53 AM » |
|
I cannot see why you'd want to do that. What's wrong with casting directly to C?
|
|
|
|
|
Logged
|
|
|
|
|
Crimsontide
|
 |
« Reply #2823 on: August 18, 2012, 06:30:17 AM » |
|
Here's an example: In my graphics library you define a format for a vertex buffer like so: struct VertexFormat { bind<FMT_WZYX32f,POSITION> pos; bind<FMT_WXYZ8,COLOR0> color; };
FMT_WZYX32f and FMT_WXYZ8 are types (4d 32-bit floating point vector and 4d 8-bit unsigned char as the latter), and bind is used by the runtime to both enumerate the struct (ensure a VertexBuffer with the given format can be used on a given VerteShader, ect...) and to bind the data to the inputs on the VertexShader (POSITION, COLOR0, ect... are semantics). Now I have a whole vector library so I usually use types like Vector<float,4> (which I use for a 4d 32-bit floating point vector). The thing is the format types (FMT_WZYX32f, FMT_WXYZ8) need to be independent types (though I have all the usual implicit conversions to and from them) as a FMT_WXYZ8 may not be the same as say a Vector<4,unsigned char>. The former is required to be exactly 32 bits long, be in little endian format, ect..., while the latter can vary based on the OS/compiler/platform/ect... So many times I need to cast from a bind<T,S> to a FMT_XXX to a Vector<T,S>, and then back again. Now I can't just add a bunch of conversions from bind<T,S> straight through to Vector<T,S>, as its not always a valid cast. Given the number of FMT_XXX's trying to enumerate all the combinations would be an immense headache, so I came up with this. Its safe (it'll throw a compile-time error if any of the casts are invalid), its precise (I know exactly what conversions take place and in what order, no surprises), and its easy to use.
|
|
|
|
|
Logged
|
|
|
|
|
Liosan
|
 |
« Reply #2824 on: August 18, 2012, 06:34:21 AM » |
|
Why would either make you nervous?
Because if you have to create a sequence of three static_casts, and because if you find using the preprocessor for such a problem rewarding, it makes me feel your coding style is waaaay different than mine. Like, alien  Liosan
|
|
|
|
|
Logged
|
|
|
|
|
Crimsontide
|
 |
« Reply #2825 on: August 18, 2012, 06:41:19 AM » |
|
Why would either make you nervous?
Because if you have to create a sequence of three static_casts, and because if you find using the preprocessor for such a problem rewarding, it makes me feel your coding style is waaaay different than mine. Like, alien  Liosan Without variadic macros I don't know of any other way to produce N versions (and retain type information) of a function for any given N (granted in this case I wouldn't go above say 3 or 4 casts). They are also used a lot in the boost libraries. Macros are useful as long as they are used sparingly IMO, some thing you just can't do any other way.
|
|
|
|
|
Logged
|
|
|
|
|
BorisTheBrave
|
 |
« Reply #2826 on: August 18, 2012, 07:36:02 AM » |
|
Without variadic macros I don't know of any other way to produce N versions.... They are also used a lot in the boost libraries.
They are really not. Where possible, boost prefers things that can be repeated indefinitely to macros/copy-pasting. Function calls are the main case where that is not possible. E.g. boost format does format("%2% %1%") % 36 % 77, where you can apply the % operator as many times as necessary. Boost lambda construts a tree of types mirroring the operators applied: _1 * 3 +1 + _2.
I'm pretty sure C++ compilers can resolve long chains of casts, but even if not, you shouldn't need to specify all the individual cases: If vector_type<FMT_WZYX32f>::type extracts the equivalent vector type for FMT_WZYX32f, and your bind type has members type and value, then you can just write: template <typename BIND_TYPE> inline vector_type<BIND_TYPE>::type vector_cast(const BIND_TYPE& v) { return static_cast<vector_type<BIND_TYPE>::type>(v.value()); }
...
Vector<unsigned char, 4> v = vector_cast(vertexFormat.pos);
|
|
|
|
|
Logged
|
|
|
|
|
Crimsontide
|
 |
« Reply #2827 on: August 18, 2012, 08:27:29 AM » |
|
Without variadic macros I don't know of any other way to produce N versions.... They are also used a lot in the boost libraries.
They are really not. Where possible, boost prefers things that can be repeated indefinitely to macros/copy-pasting. Function calls are the main case where that is not possible. E.g. boost format does format("%2% %1%") % 36 % 77, where you can apply the % operator as many times as necessary. Boost lambda construts a tree of types mirroring the operators applied: _1 * 3 +1 + _2.
I'm pretty sure C++ compilers can resolve long chains of casts, but even if not, you shouldn't need to specify all the individual cases: If vector_type<FMT_WZYX32f>::type extracts the equivalent vector type for FMT_WZYX32f, and your bind type has members type and value, then you can just write: template <typename BIND_TYPE> inline vector_type<BIND_TYPE>::type vector_cast(const BIND_TYPE& v) { return static_cast<vector_type<BIND_TYPE>::type>(v.value()); }
...
Vector<unsigned char, 4> v = vector_cast(vertexFormat.pos);
I know boost::function uses macros extensively. And I'm sure I've seen it used elsewhere in the Boost src but I can't remember off the top of my head. And yes, I could have done something like you mentioned, but that would only work for that one specific case. Ahh well, to each his own I guess. Btw, isn't the inline in the function you specified above redundant, given that its a template function?
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #2828 on: August 18, 2012, 10:33:26 AM » |
|
Btw, isn't the inline in the function you specified above redundant, given that its a template function?
For linkage purposes, yes. For optimization hinting purposes, no.
|
|
|
|
|
Logged
|
|
|
|
|
Crimsontide
|
 |
« Reply #2829 on: August 18, 2012, 11:50:25 AM » |
|
Btw, isn't the inline in the function you specified above redundant, given that its a template function?
For linkage purposes, yes. For optimization hinting purposes, no. It was my understanding that inline as used for optimization was pretty much obsolete. Does any modern compiler actually use it anymore?
|
|
|
|
|
Logged
|
|
|
|
|
Average Software
|
 |
« Reply #2830 on: August 18, 2012, 11:57:34 AM » |
|
Btw, isn't the inline in the function you specified above redundant, given that its a template function?
For linkage purposes, yes. For optimization hinting purposes, no. It was my understanding that inline as used for optimization was pretty much obsolete. Does any modern compiler actually use it anymore? GCC uses it for certain purposes, I can't speak for others. As an example, there's -fkeep-inlines, which forces a non-inline copy of any function declared inline to be added to each object file, even if it's inlined at every call site. I'd reckon you could find similar switches for other compilers.
|
|
|
|
|
Logged
|
|
|
|
|
rivon
|
 |
« Reply #2831 on: August 18, 2012, 01:08:25 PM » |
|
As an example, there's -fkeep-inlines, which forces a non-inline copy of any function declared inline to be added to each object file, even if it's inlined at every call site. What did you just say? I'm quite good at English but I can't understand what you just said...
|
|
|
|
|
Logged
|
|
|
|
|
indietom
|
 |
« Reply #2832 on: August 18, 2012, 01:37:16 PM » |
|
I made the best program ever.
int brake = 10 / 0; cout << brake;
|
|
|
|
|
Logged
|
Code::Blocks This is my profile, there are many like it but this one is mine.
|
|
|
|
RobJinman
|
 |
« Reply #2833 on: August 24, 2012, 07:11:01 AM » |
|
This doesn't have anything to do with games, but I'm happy because I got maths to render nicely on my website ( http://robjinman.com/article.jsp?id=34). It looks pretty  I used Mathjax, which is really easy to use, and is compatible with XHTML too. Initially I tried jqMath, but it didn't work in IE -- it was trying to call Document.write(), which is not allowed in XHTML. Once all the basic subsystems of my 'engine' are done, I intend to work on some more algorithm-y stuff, and document my progress on my blog -- hence the need to render maths nicely.
|
|
|
|
|
Logged
|
|
|
|
|
Quarry
|
 |
« Reply #2834 on: August 24, 2012, 11:33:41 AM » |
|
I made the best program ever.
int brake = 10 / 0; cout << brake;
What does it print
|
|
|
|
|
Logged
|
|
|
|
|