My question is, is this method OK?
Think about the readability. Wouldn't
throw CUnexpectedEndOfStream();
be more readable than
throw -2
?
And in a lot of cases wouldn't seeing an instance of CUnexpectedEndOfStream thrown in the debugger mean TONS more than -2. That's not to mention that CUnexpectedEndOfStream could store gobs of useful information about the problem such as say the file that couldn't be read and maybe more info on the nature of the problem.
Or should I throw a exception derived from std::exception?
Inheriting from std::exception
may be helpful if that's how you choose to organize your other exceptions. It a convenient base class that client code can use. Also depending on the exception you may want to use std::runtime_error.
Is throwing int exceptions bad practice? (all throw int values are documented in doxygen comments)
Who said it was bad practice? Throwing exceptions is a great way to handle exceptional situations. Most of the exceptions I throw are because of something that could have been prevented by the client code doing what it was supposed to-- the user of my code violated the contract. But many other exceptional non-normal cases also exist like OS errors, disks filling up, etc. All the things that aren't part of your programs normal flow. More importantly, since they're not part of your program's normal flow, you don't need to worry about performance.
As an example, I once used exceptions to trigger that a certain message parsing failure occurred. However, I found that these parsing errors occurred frequently to the point where I started handling exceptions and fixing the problem input and reparsing. After a while, I realized that a more readable solution would be to fix the problem directly in the parsing code and stop treating it like an exceptional case. All the code that made parsing decisions was put back in one place and I wasn't throwing exceptions like a drunken sailor throws out curse words.