Sign in to follow this  

Any alternatives to automatic class instantiation via macro?

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

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

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

Just a minor Urho-related correction: the Application class is an optional helper, not the "core of the engine". The most useful thing it does, for simple applications which don't need more sophisticated control, is to abstract away how the platform wants the main loop to be run, which differs on iOS and Emscripten ("run one frame when requested" instead of "run in a loop forever until exited"), but you're not forced to use it.

Share this post


Link to post
Share on other sites

Just a minor Urho-related correction: the Application class is an optional helper, not the "core of the engine". The most useful thing it does, for simple applications which don't need more sophisticated control, is to abstract away how the platform wants the main loop to be run, which differs on iOS and Emscripten ("run one frame when requested" instead of "run in a loop forever until exited"), but you're not forced to use it.

Wow really? I must of been looking at the architecture of it wrong them. It appeared to me that the Application class was the root of the engine and from there initialized all of the subsysems.

Share this post


Link to post
Share on other sites

It's possible it's not documented strongly enough that it's a helper only. And it's also extensively used by all the included samples :)

 

But anyway, there's the Engine class that does that actual work (and which is simply instantiated by Application, which you could also do yourself.) Even that isn't strictly mandatory, if you know what you're doing you can instantiate only the subsystems you need, but then we're deep in "advanced use" territory.

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.
 

 

I'm with this guy ^

A DI framewor would suit your issue.

---

tl;dr : Let the user define your the main, tell him to call app.run(). 

---

If we think about the strategy pattern (I may over-abuse it , but this is subjective), you should have a main entry point and something(class) that initialize your core functionality. 

Either you set the entry point, or the user that consumes your library. 

A macro does not suit it because you have no control over it. Just some static code compiling. (So what's the difference, you just saved yourself 3 lines of code).

Therefore we need to think in terms of "changable objects". Which is your base application class.

I think inheritance should be used when dealing with the application class. Because there should be only one! (<- Entry point here).

So if we mix everything up, you let the user define the main entry point and some class that should be initialized and run.

Your behavior, should be initialization of library's features. (before or at run() ).

 

For example, If I take the library glew. It does not want to take control over my main function because it needs initialziation.

It tells me explicity : "Call glewInit()". 

So you need to tell explicity your users "call App.run()". 

This is an acceptable behavior, just be sure that it suits your needs. 

Edited by WoopsASword

Share this post


Link to post
Share on other sites

This topic is 678 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this