If using exception means that every call that might throw is surrounded by try-catch, the concept is misunderstood. Exceptions are great precisely because they needn't be handled directly but can be propagated to a higher-level function instead. That is, a function might load several videos just like this:
video1.load(...);
video2.load(...);
video3.load(...);
And in another function there is a try-catch clause. If you derive your exceptions from std::runtime_error, one can even abstract this away and check for general errors.
But error codes also a possibility if you want your library to be similar to SFML in terms of usability. But as you mention, it's difficult to specify more about the error. SFML uses the sf::err() stream to output error description. However that's only suitable for debugging purposes, you cannot react on a specific error.
Concerning the namespace, I think sfmod and sfmidi are okay, for SFMLTheora an option might also be sftheora (it's still long, but better than SFMLTheora, also because of the case). But as I'm currently also having a namespace problem (http://en.sfml-dev.org/forums/index.php?topic=7330.msg48459#msg48459), I'm probably not the best to give advice :P
majority of the people (working with games) don't favor exceptions.
Is that true? I'd like to learn about the backgrounds, have you read that somewhere or is it rather your general impression?
I've read it in various places, you can google c++ exception handling in games.
The results, of course, consists of those who support that idea, and those who are against that idea.
And after reading those, especially the discussion-types (rather than articles), I find that most people seem to recommend against using it (for my situation).
Also, most libraries I've came across with don't use exceptions, so maybe there's a bit of general impression in my statement above as well.
SFML doesn't use exceptions (for now), but if it does (SFML 3?), I will probably change mine to use it too, I will explain why below.
I don't understand that, why does one need the heap?
For example, this code:
sftheora::Video testVid("video.ogg");
if (sftheora::hasError())
// Handle error
Will have to translate into either 1 of these 3 if I decided to use exceptions:
try {
sftheora::Video testVid("video.ogg");
// Main loop << Forces user to put main loop here
}
catch (exception) {
// Handle exception
}
or
sftheora::Video* testVid;
try {
testVid = new sftheora::Video("test.ogg"); // Forces user to use heap
}
catch (exception) {
// Handle exception
}
// Rest of code
or
sftheora::Video testVid;
try {
testVid.load("test.ogg");
}
catch (exception) {
// Handle exception
}
However, if Laurent decides to use exceptions for SFML, I will switch to it as well, since if that's the case, the user will probably have most of his (initialization) code in try-catch blocks anyway, so I'll just make use of that.
The problem with this approach is that you have objects which aren't operational. You can't rely on a valid object state, which makes ugly validity checks necessary. And you need to define semantics for an unloaded object -- what should video.play() do if it the video has not been loaded?
The additional issue with hasError() is, that it has global state and needs to be invoked directly after each constructor in order to find out which one failed. Same with getError(), it only reports the last error.
Currently, I leave the responsibility of checking whether the object is valid after loading it to the user.
Just like if creating an object on the heap, if you don't null-check it and it unexpectedly returns a null (probably due to bad allocation), the program will crash (ugly, indeed).
I follow that "rule" as well, if you don't check if it's valid after loading it, you risk having your program crashed.
Also, hasError() does not have a global state, the error string is just another (private) variable of each instance. It is different from std::cerr or sf::err(). It is more like an optional explanation of what went wrong, in addition to the boolean value.
While it only reports the last error, why would you need it to report any other previous errors?
In exceptions, you only get the exception once, and that's it, it's the same for this, just that you have to manually clear the error if you decide to continue using that same instance.