Tips for avoiding Compile-Time errors with Metaprogramming

Started by
5 comments, last by coope 8 years, 6 months ago

So I recently began an undertaking to convert all the core functionality of a simple engine I made into libraries so that I can compile a lot faster. When I sat down and started breaking things down I realized adding some functionality would make the task easier.

I have added an asset allocator, will be adding an asset factory, and am currently trying to add an asset pool. All of these classes have been designed with template methods. I even figured out how to prevent compilation of the methods when used with an object not derived from my GameAsset class. I needed a way to compare types, and a friend suggested I avoid RTTI. So I solved my problem with another metaprogramming solution.

Which is as follows:

1.) Create a simple class(Registrar) with a static counter which can provide unique type ids as unsigned int values starting at 1.

2.) Create a template singleton class(RegistryEntry<T>) which will access Registrar and store the unique id acquired.

The usage was intended to be quite simple with RegistryEntry<T>::Instance().Get_ID(); I even implemented a macro to perform the implementations of the TypeID() virtual method inside the GameAsset classes. This is where I am now.

The post-instigating problem is that I can't tell if some code will compile properly in 2 or 3 weeks when I am ready to compile code which will test these new features. Which is bad if you ask me, I'd like to know if something is going to compile before I start building upon it. The code is this line: RegistryEntry<T>::Instance().Get_ID(); The syntax is clearly highlighted, properly, by vs2013 intellisense but only for the macro. My use in the Asset_Pool class is not highlighted though.

class Asset_Pool is not a template however the method Get(uint N) is.

method signature is just this:

template<class T>
T* Get(uint N)

My first thought was that intellisense is just acting up as it often does and was merely unable to deduce the implied meaning of the line of code without a thorough look(ie. compiling it). Then I thought how awful it would be if I had to rewrite a bunch of code if this line won't compile.

So I am hoping there are some opinions, advice, and general tips to curb such problems. Perhaps a way to deduce on my own whether syntax isn't highlighting because I screwed up or because intellisense screwed up.

As a side note, I'm sorry I couldn't generalize the post as much as I'd like to given the topic title.

Advertisement

Moved to General Programming.

So I am hoping there are some opinions, advice, and general tips to curb such problems. Perhaps a way to deduce on my own whether syntax isn't highlighting because I screwed up or because intellisense screwed up.


Generally, don't do big giant refactors without testing things along the way. You can test core ideas like your type registry without having to have already converted all your code to use it.

Intellisense is not a replacement for just knowing C++, though. For instance, I can look at your simple Get function template and tell you for sure it is a 100% valid declaration. I don't need hightlighting or color coding to tell me that, and you shouldn't either. Color-coding should help you work faster, but not be necessary to work at all.

Sean Middleditch – Game Systems Engineer – Join my team!

You are doing something wrong if you are not compiling your code in 2 or 3 weeks... its way better to just test small pieces of code. If you are doing something fancy with TMP, then you could isolate the fancy stuff in a sandboxed small test and run it.

I'd first like to mention that adding templated code isn't going to help your compile times; if anything, it may slow them down considerably. However it likely won't make a huge different for small codebases, and compile times shouldn't be your first priority unless they're really hindering your workflow.

Second, you should be creating some unit tests along with your new libraries in order to test everything out before it even touches your main code. Writing code that compiles is easy, but that's not what you're really testing.

You avoid RTTI, and then implement your own version of it, it seems to me?

Or am I missing something?

If I am correct, it may be useful to do a comparison between both solutions, before discarding a native solution.

Great advice guys, thanks!

What I am getting is this:

* Have more confidence in my syntactical knowledge

* Don't rely on intellisense to spot syntactical issues

* Test new designs in test projects before implementing in complex projects

* Compile more frequently - (though, what I meant was I'd be compiling the original project which is where I'd likely be performing unit tests)

* Continue my practice of unit testing systems and components

I'd first like to mention that adding templated code isn't going to help your compile times; if anything, it may slow them down considerably. However it likely won't make a huge different for small codebases, and compile times shouldn't be your first priority unless they're really hindering your workflow.

I know the templates will need to compile every time. Adding these 3 features was more of a way to centralize my core game assets like textures, and meshes to name two. All of which will be compiled into a static library and included with these features. The compiling has recently become an issue of annoyance because more times than not I have to compile twice due to an error writing to either the .exe or the .ilk(?). I can't remember the second extension type, but I believe it was the symbol debug info. This problem would sometimes cause the entire project to need recompiling instead of just the files I was working on or affected by changes I made.

it may be useful to do a comparison between both solutions, before discarding a native solution.

I did so just now. Mine does generate an entire object, to merely store an id, for every type I register; however the size requirements are small due to the implementation details. RTTI in comparison makes an object for every class type in the codebase. In an article I found on native RTTI I also saw that there appears to be boundary issues where comparing types can only be resolved by a string comparison of the type_trait's name. Although I think I could have easily gone either way with little issue, it seems my solution will guarantee quick comparison and can be reserved for types I need to manage with type comparisons. Though my solution does require a bit more work on my part.

This topic is closed to new replies.

Advertisement