When delivering an API to you often have to declare error codes (most often as int
) and later you often want to provide a function converting a int
error code to std::string
to be able to report the error to the user in a smart way.
I found some posts on how to maintain the int
/std::string
mapping programmatically, like this one: Mapping error codes to string in C++
Now, I was wondering, why not simply return a std::string
rather than a int
? Empty string would mean no error, anything else would mean error + provide a human readable message.
Let's obviously assume you don't care about memory usage and performances (your API has functions not called that often and time of execution is not critical).
If you need the client to be able to do some specific operations programmatically, error codes could be declared as constants. But you don't need any int
to std::string
mapping anymore. As an example, it would be:
Declaration:
static const std::string successMessage;
static const std::string fileDoesNotExistMessage;
static const std::string internalErrorMessage;
std::string openFile( const std::string& fileName );
Implementation:
static const std::string successMessage = "";
static const std::string fileDoesNotExistMessage = "File does not exist";
static const std::string internalErrorMessage = "Internal error";
std::string openFile( const std::string& fileName )
{
if ( ... ) // test file existance
{
if ( ... ) // internal tests
return internalErrorMessage;
else
return successMessage;
}
else
{
return fileDoesNotExistMessage ;
}
}
API user can then do:
int main()
{
std::string error = openFile( "file.txt" );
if ( error.empty() )
{
std::cout << "File was successfully opened" << std::endl;
}
else if ( error == fileDoesNotExistMessage )
{
// specific error handling
}
else
{
std::cout << "Unable to open file, error reported is " << error << std::endl;
}
}
Advantages:
- No risk to have a
int
/std::string
broken mapping - Easy to add error codes on the fly
- Easy to maintain
There must be disavantages, because I know no open source library using this approach...any idea why?