Jump to content
  • Advertisement
Sign in to follow this  
Renthalkx97

Any alternatives to automatic class instantiation via macro?

This topic is 892 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

Hey! So before I explain what I'm doing, I'd like to first off say I got this idea from the Urho3D Engine http://urho3d.github.io/

 

Basically, they have the Application class as the core of their engine, and you inherit your own application from that class. You then implement your own versions of the relevant methods. There is then a macro that is called that you pass your app's class name to which essentially creates an object of your class for you and does all the internal initialization. So in other words, you have zero interaction with the internals of the engine. You don't need to explicitly call any functions to start up your app. The macro takes care of all of that.

 

Simplified version:

#define APPLICATION_MAIN(applicationClassName)\
int ApplicationMain(int argc, char **ppArgv)\
{\
    applicationClassName application(...);\
    return application.Run();\
}

And the application of this:

class MyApp : public Application
{
};

APPLICATION_MAIN(MyApp)

The alternative to this as far as I can tell is having the user manually instantiate their class inside of some designated platform-independent main function that gets called from the platform's main function. 

 

Eg:

int SomeCustomMain(int argc, char **ppArgv)
{
    MyAppClass myApp(...);

    return myApp.Run();
}

I like the idea of the user not having to directly instantiate their class (since it's done indirectly via the macro), but I am wondering if there is a way to accomplish this same feature without using a macro. I have yet to come up with anything. This is using the preprocessor to manipulate the source to use your derived class name instead of the base class name. And that's not possible via any language features, so I don't know.

 

Any ideas?

Edited by BagelBytes

Share this post


Link to post
Share on other sites
Advertisement

Templates can get you most of the way there, but you can't literally define a new function at compile time with a C++ template (as far as I know).  I'm skeptical of how useful this pseudo-DI thing is in practice though.  You're only saving a few lines of boiler-plate, unless you want to extend it for a whole bunch of other dependencies, at which point you should probably look for some kind of DI framework.
 

Share this post


Link to post
Share on other sites

Templates can get you most of the way there, but you can't literally define a new function at compile time with a C++ template (as far as I know).  I'm skeptical of how useful this pseudo-DI thing is in practice though.  You're only saving a few lines of boiler-plate, unless you want to extend it for a whole bunch of other dependencies, at which point you should probably look for some kind of DI framework.
 

 

Yeah, I considered using templates, but it still wouldn't be possible to do this exactly using them. I just really liked the idea of just simply extending a built-in class and leaving it at that. You don't need declare any objects/call any functions. Perhaps I am being too user friendly, though. I don't know. I just wanted to get some opinions on it. It's not a deal-breaking feature I need to have by any means.

Share this post


Link to post
Share on other sites

SDL used to hijack main() with a macro on Mac and Windows.

 

They still do on Windows. It's called SDL_main (the macro), I believe.

Edited by BagelBytes

Share this post


Link to post
Share on other sites
I'm going to cast a vote in favor of letting the user have control of the lifetime of the objects. Magic systems that purport to make life "simpler" usually backfire.

Share this post


Link to post
Share on other sites

Thank you everyone for the replies.

 

@Sean I agree. I can see how inheriting everything from some base app class can cause issues and make the code much harder to maintain. Although I don't believe my project will reach that amount of complexity anytime soon, no sense in writing something I'll have difficulty in expanding on later.

 

And generally, I do tend to favor composition over inheritance, I just saw how Urho3D did it and it sparked my interest. Nonetheless, I'll be doing some refactoring most likely.

 

Thank you again for your guys' input!

Share this post


Link to post
Share on other sites
If you're keen on it, put it into a "helper"/"utility" layer that's optional. It only saves you 3 lines of code, once in thr entire application -- macros are generally used where they'll be paying off more than that.

Also, I'd personally find it more idiomatic for thr "app" object to be executed via operator() rather than a named method, and would call the macro something like:
#define DECLARE_MAIN(T)\
int main(int argc, char **argv){\
    T app(argc, argv);\
    return app();
}
If you're porting to a bunch of different platforms, which all use non-standard names for the main function, then it might be handy to have a wrapper for "main". This is common on engines that need to run in different environments, such as Java, .NET, etc as well as "native apps" -- i.e. on some platforms you can't write your main function in C/C++!
In that situation, you'd write a standard main for every platform which then calls out to some forward-declared but non-existent custom-main function that the user can implement.

Alternatively, if you want to force the user to use a "main object" like in your example, you could use your macro, or force the user to define it as a compiler -D option, e.g. your engine might include:
int main(int argc, char **argv){
#ifndef MAIN_CLASS
#error "You must define MAIN_CLASS when compiling the engine"
#endif
    MAIN_CLASS app(argc, argv);
    return app();
}
Or you can simply declare the main class but not implement it:
//app.h
class Main { public:
  Main( int argc, char** argv);
  int Run();
void* userdata;
};
//Engine.cpp
int main(int argc, char **argv){
    Main app(argc, argv);
    return app.Run();
}

//MyExe.cpp
#include "app.h"
Main::Main( int argc, char** argv) { userdata = 0; }
int Main::Run()
{ return 42; }
But I agree with others that it's better to let the app write it's own main function...

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!