Translate error codes to string to display - c++

Is there a common way in C++ to translate an error code to a string to display it?
I saw somewhere a err2msg function, with a big switch, but is that really the best way?

Since C++ does not allow automatic 'translation' from enum values to enum names or similar, you need a function to do this. Since your error codes are not somehow defined in your O/S you need to translate it by yourself.
One approach is a big switch statement. Another is a table search or table lookup. What's best depends on error code set.
table search can be defined in this way:
struct {
int value;
const char* name;
} error_codes[] = {
{ ERR_OK, "ERR_OK" },
{ ERR_RT_OUT_OF_MEMORY, "ERR_RT_OUT_OF_MEMORY" },
{ 0, 0 }
};
const char* err2msg(int code)
{
for (int i = 0; error_codes[i].name; ++i)
if (error_codes[i].value == code)
return error_codes[i].name;
return "unknown";
}

In windows you can use FormatMessage(...) function either with error code return by GetLastError() function or directly to the suspected area.
Please see below links for examples.
http://msdn.microsoft.com/en-us/library/ms679351(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms680582(v=VS.85).aspx
I hope this will help you.

Similar to harper's idea, but a bit more generalized:
typedef std::map<int, const char*> error_code_tbl_t;
typedef error_code_tbl_t::value_type error_code_entry_t;
const error_code_entry_t error_code_tbl_[] = {
{ ERR_OK , "ERR_OK" },
{ ERR_RT_OUT_OF_MEMORY, "ERR_RT_OUT_OF_MEMORY" },
// ...
};
const error_code_tbl_t error_code_tbl( begin(error_code_tbl_)
, end (error_code_tbl_) );
const char* err2msg(int code)
{
const error_code_tbl_t::const_iterator it = error_code_tbl.find(code);
if(it == error_code_tbl.end())
return "unknown";
return it->second;
}
(Those begin() and end() functions can be found here.)

As far as I am concerned, error codes are just a subset of enums. Since we are not blessed in C++ with pretty enums (which makes logs somehow quite hard to parse), error codes are no more easier.
The solution is pretty simple for error codes though:
class ErrorCode
{
public:
ErrorCode(): message(0) {}
explicit ErrorCode(char const* m): message(m) {}
char const* c_str() const { return message; }
std::string toString() const
{
return message ? std::string(message) : std::string();
}
private:
char const* message;
};
std::ostream& operator<<(std::ostream& out, ErrorCode const& ec)
{
return out << ec.c_str();
}
Of course you can supply the traditional ==, !=, <, etc...
It's simple!
It's fast (the code IS the string, no look-up involved)
It's type safe (you cannot accidentally mix it up with another type)
The idea is to return pointers to the text instead of error codes (though wrapped in a class for type safety).
Usage:
// someErrors.h
extern ErrorCode const ErrorOutOfMemory;
// someErrors.cpp
ErrorCode const ErrorOutOfMemory = ErrorCode("OUT OF MEMORY");

The big switch is not that bad for this. To get a string for an error code is almost always not performance critical.
You should keep in mind that these error strings are probably not what you want to show your users. The messeges for the user should be kept in resources for easier translation.
strings for error codes are for logs or diagnostics and need no translation.
You can use this trick to define your error codes and the strings in parrallel:
#if defined(ERROR_BUILD_ARRAY)
#define ERROR_START \
static const err_defn error_table[] = { \
{ WARNING, "Warning" },
#define ERRDEF(num, offset, str) { num, str },
#define ERROR_END { 0, NULL } };
#elif !defined(ERROR_ENUM_DEFINED)
#define ERROR_START \
typedef enum svn_errno_t { \
WARNING = OS_START_USERERR + 1,
#define ERRDEF(num, offset, str) /** str */ num = offset,
#define ERROR_END ERR_LAST } svn_errno_t;
#define ERROR_ENUM_DEFINED
ERROR_START
ERRDEF(ERR_BAD_BAD,
ERR_BAD_CATEGORY_START + 0,
"Bad error")
ERRDEF(ERR_BAD_FILENAME,
ERR_BAD_CATEGORY_START + 1,
"Bogus filename")
ERROR_END
(Copied from subversion sources)

I tend to avoid the switch since it's usually a big piece of code. I prefer a table lookup along the lines of:
In btree.h:
enum btreeErrors {
ZZZ_ERR_MIN = -1,
OKAY,
NO_MEM,
DUPLICATE_KEY,
NO_SUCH_KEY,
ZZZ_ERR_MAX };
In btree.c:
static const char *btreeErrText[] = {
"Okay",
"Ran out of memory",
"Tried to insert duplicate key",
"No key found",
"Coding error - invalid error code, find and destroy developer!"
};
const char *btreeGetErrText (enum btreeErrors err) {
if ((err <= ZZZ_ERR_MIN) || (err >= ZZZ_ERR_MAX))
err = ZZZ_ERR_MAX;
return btreeErrText[err];
}
Not that it usually matters since errors should be the exception rather than the rule, but table lookups are generally faster than running big switch statements (unless they get heavily optimised).

I wanted a way to have error code (int) and string description (any string) be declared in one and only one single place and none of the examples above allows that (ERR_OK has to be declared somewhere and then "ERR_OK" is mapped to it somewhere else).
So I declared a simple class storing both int and string and maintaining a static map for int->string conversion. I also added an "auto-cast to" int function:
class Error
{
public:
Error( int _value, const std::string& _str )
{
value = _value;
message = _str;
#ifdef _DEBUG
ErrorMap::iterator found = GetErrorMap().find( value );
if ( found != GetErrorMap().end() )
assert( found->second == message );
#endif
GetErrorMap()[value] = message;
}
// auto-cast Error to integer error code
operator int() { return value; }
private:
int value;
std::string message;
typedef std::map<int,std::string> ErrorMap;
static ErrorMap& GetErrorMap()
{
static ErrorMap errMap;
return errMap;
}
public:
static std::string GetErrorString( int value )
{
ErrorMap::iterator found = GetErrorMap().find( value );
if ( found == GetErrorMap().end() )
{
assert( false );
return "";
}
else
{
return found->second;
}
}
};
Then, you simply declare your error codes as below:
static Error ERROR_SUCCESS( 0, "The operation succeeded" );
static Error ERROR_SYSTEM_NOT_INITIALIZED( 1, "System is not initialised yet" );
static Error ERROR_INTERNAL( 2, "Internal error" );
static Error ERROR_NOT_IMPLEMENTED( 3, "Function not implemented yet" );
Then, any function returning int can do to return 1
return ERROR_SYSTEM_NOT_INITIALIZED;
And, client programs of your library will get "System is not initialised yet" when calling
Error::GetErrorString( 1 );
The only limitation I see is that static Error objects are created many times if .h file declaring them is included by many .cpp (that's why I do a _DEBUG test in constructor to check consistency of the map). If you don't have thousands of error code, it should be a problem (and there may be a workaround...)
Jean

Related

Efficiently iterating through a database row (libpqxx), assigning values to a struct

I'm grabbing a row from a database using libpqxx and assigning the fields within the pqxx::row to a struct specifically designed to hold those values:
struct driveOperationRecord
{
long int id = 0;
long int drive_operator_id = 0;
long int operator_operation_index = 0;
long int specific_operation_id = 0;
bool operation_outcome = false;
std::string error_code = "";
long int operation_seconds = 0;
std::string operation_date = "";
std::string serial_number = "";
std::string model = "";
long long int size = 0;
std::string firmware = "";
};
To do this I'm currently using the following code:
void driveOperationEntryToRecord(pqxx::row entry, driveOperationRecord& record)
{
try
{
if (!entry["id"].is_null()) record.id = entry["id"].as<int>();
if (!entry["drive_operator_id"].is_null()) record.drive_operator_id = entry["drive_operator_id"].as<int>();
if (!entry["operator_operation_index"].is_null()) record.operator_operation_index = entry["operator_operation_index"].as<int>();
if (!entry["specific_operation_id"].is_null()) record.specific_operation_id = entry["specific_operation_id"].as<int>();
if (!entry["operation_outcome"].is_null()) record.operation_outcome = entry["operation_outcome"].as<bool>();
if (!entry["error_code"].is_null()) record.error_code = entry["error_code"].as<std::string>();
if (!entry["operation_seconds"].is_null()) record.operation_seconds = entry["operation_seconds"].as<long int>();
if (!entry["operation_date"].is_null()) record.operation_date = entry["operation_date"].as<std::string>();
if (!entry["serial_number"].is_null()) record.serial_number = entry["serial_number"].as<std::string>();
if (!entry["model"].is_null()) record.model = entry["model"].as<std::string>();
if (!entry["size"].is_null()) record.size = entry["size"].as<long long int>();
if (!entry["firmware"].is_null()) record.firmware = entry["firmware"].as<std::string>();
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
Which is absolutely horrible and I hate it. I've thought about using a switch with an appropriate enum but iterating through a switch 12 times feels even worse. Ideally I'd be able to use something like:
for (auto field : entry)
{
if (!field.is_null()) record.<if only i could dynamically reference using field.name()> = field.as<somehow magically find appropriate type>();
}
But these things are impossible. Any ideas?
EDIT (In response to Useless):
The current database contains roughly 4,000 entries which will need to pass through this function on a fairly regular basis. It is expected to grow exponentially from here. In order to future proof, operational efficiency is also important. I am fairly new to c++ and I know that there is a lot that I don't know! I was just really hoping to find something slightly more elegant and have really been struggling to do so.
for (auto field : entry)
{
if (!field.is_null()) record.<if only i could dynamically reference using field.name()> = field.as<somehow magically find appropriate type>();
}
This is entirely feasible, although not quite like this.
Let's just assume we can have some record of what fields driveOperationRecord (henceforth just Record, for brevity) supports, along with their names, and types, and which data member they correspond to. Then we can walk over them, like:
for (auto& field : record_fields)
{
field.assign(row, record);
}
Now we need some field-describing type like
struct FieldDescriptor
{
std::string name_;
void assign(pqxx::row const& row, Record& record)
{
auto entry = row[name_];
if (!entry.is_null()) {
// do something
}
}
};
So far so good. The "do something" step is where we need to use something like virtual dispatch, because we're handling different types.
We could enumerate all the types we care about and write a big switch statement, but it's tedious. I'd start with the simplest thing first, and do something more complex if it turns out you really need it to be faster:
struct FieldDescriptor
{
std::string name_;
std::function<void(pqxx::field const&, Record&)> assign_;
void assign(pqxx::row const& row, Record& record)
{
auto entry = row[name_];
if (!entry.is_null()) {
assign_(entry, record);
}
}
};
OK, so now we just need some way to build a function or callable object similar to
void assignFieldName(pqxx::field const& entry, Record& record) {
record.fieldName = entry.as<decltype(record.fieldName)>();
}
For example, we could write
template <typename RecordType, typename FieldType>
FieldDescriptor describe(const char *name, FieldType RecordType::*member)
{
return
{ std::string{name},
[=member](pqxx::field const& entry, Record& record)
{
record.*member = entry.as<FieldType>();
}
};
}
and even wrap it up in a macro to save a little more typing:
#define DESCRIBE_RECORD_FIELD(F) describe(#F, &Record:: F)
FieldDescriptor record_fields[] = {
DESCRIBE_RECORD_FIELD(id),
DESCRIBE_RECORD_FIELD(drive_operator_id),
DESCRIBE_RECORD_FIELD(operator_operation_index),
DESCRIBE_RECORD_FIELD(specific_operation_id),
DESCRIBE_RECORD_FIELD(operation_outcome),
DESCRIBE_RECORD_FIELD(error_code),
DESCRIBE_RECORD_FIELD(operation_seconds),
DESCRIBE_RECORD_FIELD(operation_date),
DESCRIBE_RECORD_FIELD(serial_number),
DESCRIBE_RECORD_FIELD(model),
DESCRIBE_RECORD_FIELD(size),
DESCRIBE_RECORD_FIELD(firmware)
};
Now, we have sort of shadowed the whole definition of Record again, which is unfortunate. It's possible to avoid this ... but only by replacing the whole definition with a bunch of macros that do double duty declaring the members, and registering their descriptors.
For a small number of records, I'd probably stick with what we have here. If there are a lot, it's worth making more effort to automate (and to make sure the definition can't get out of sync with the registered descriptors).
If all else fails, you can always go old school to avoid tedious and error prone repetition:
#define ENTRY_TO_RECORD(TYPE) \
{
auto e = entry[#NAME]; \
if (!e.is_null()) {\
record.NAME = e.as<decltype(NAME)>(); \
} \
}
void driveOperationEntryToRecord(pqxx::row entry, driveOperationRecord& record)
{
try
{
ENTRY_TO_RECORD(id);
ENTRY_TO_RECORD(drive_operator_id);
ENTRY_TO_RECORD(operator_operation_index);
ENTRY_TO_RECORD(specific_operation_id);
ENTRY_TO_RECORD(operation_outcome);
ENTRY_TO_RECORD(error_code);
ENTRY_TO_RECORD(operation_seconds);
ENTRY_TO_RECORD(operation_date);
ENTRY_TO_RECORD(serial_number);
ENTRY_TO_RECORD(model);
ENTRY_TO_RECORD(size);
ENTRY_TO_RECORD(firmware);
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
Yeah, I know this is generally frowned upon, and I should say that there's all sorts of caveats with using precompiler macros (like, don't put them in your header files).
So probably just consider this a temporary workaround while someone comes back with a more idiomatic solution.

c++ Externally visible const

I have a function which returns zero on success, or the line number where an error was detected:
int func() {
// stuff
if (something is wrong) {
return __LINE__;
}
// more stuff
if (something else is wrong) {
return __LINE__;
}
// all good
return 0;
}
Real callers only check whether the return value is zero or not, often like this:
int ret = func();
if (ret != 0) {
return ret;
}
However, during tests I would like to check the actual return value, to verify that a certain fail condition was triggered:
int ret = func();
EXPECT_EQ(42, ret);
This poses a problem, because when the source file of func() is edited, the lines of the return statements, and hence the values returned, also change. I would like the line number values to be available to the callers of func().
It is possible to "export" line numbers like this:
// header
extern const int line_number;
// source
const int line_number = __LINE__;
Unfortunately, this only works for line numbers outside a function. I would like something like this:
if (something is wrong) {
const int line_number = __LINE__; return __LINE__;
// or some other const thing
}
that can be read from another translation unit (file).
I tried static const int line = __LINE__, but that has two flaws:
it's not the definition of line_number declared in the header.
it may not be set until execution passes over it.
Here an example how I would solve this easily:
struct FuncErrorCodes {
enum Type {
OK = 0,
SOMETHING_IS_WRONG,
SOMETHING_ELSE_IS_WRONG,
...
};
};
typedef FuncErrorCodes::Type FuncErrorCode;
FuncErrorCode func() {
// stuff
if (something is wrong) {
return FuncErrorCodes::SOMETHING_IS_WRONG;
}
// more stuff
if (something else is wrong) {
return FuncErrorCodes::SOMETHING_ELSE_IS_WRONG;
}
...
// all good
return FuncErrorCodes::OK;
}
I don't see any reason why I would want to use __LINE__ for error codes.
In the usual case the return code can still be tested against 0 (or better yet FuncErrorCodes::OK) and I'd have no problem testing for the particular error reasons, like for example:
FuncErrorCode rc = func();
EXPECT_EQ(FuncErrorCodes::SOMETHING_IS_WRONG, ret);
EDIT: Note that even if you managed to export the "last line set to the error code" it would not help you in any way, because that would be the exact value the function is returning (so you already know it). For it to actually work, you would need separate variable for each possible error line, which will then contain the particular line number (so that it can be checked against the function return code to see if the particular error happened).
I.e. you would need something like:
extern int something_wrong_line_number;
extern int something_else_wrong_line_number;
if (something is wrong) {
something_wrong_line_number = __LINE__; return __LINE__;
}
if (something else is wrong) {
something_else_wrong_line_number = __LINE__; return __LINE__;
}
// etc. - but it will of course still not work entirely well because the __LINE__ is only assigned if the error actually happens
And that is then no different to providing just the simple error codes for each particular error situation as I suggest (and it is much more complicated).

C++ similar behavior to java.lang.Enum<E> [duplicate]

It is common knowledge that built-in enums in C++ are not typesafe.
I was wondering which classes implementing typesafe enums are used out there...
I myself use the following "bicycle", but it is somewhat verbose and limited:
typesafeenum.h:
struct TypesafeEnum
{
// Construction:
public:
TypesafeEnum(): id (next_id++), name("") {}
TypesafeEnum(const std::string& n): id(next_id++), name(n) {}
// Operations:
public:
bool operator == (const TypesafeEnum& right) const;
bool operator != (const TypesafeEnum& right) const;
bool operator < (const TypesafeEnum& right) const;
std::string to_string() const { return name; }
// Implementation:
private:
static int next_id;
int id;
std::string name;
};
typesafeenum.cpp:
int TypesafeEnum::next_id = 1;
bool TypesafeEnum::operator== (const TypesafeEnum& right) const
{ return id == right.id; }
bool TypesafeEnum::operator!= (const TypesafeEnum& right) const
{ return !operator== (right); }
bool TypesafeEnum::operator< (const TypesafeEnum& right) const
{ return id < right.id; }
Usage:
class Dialog
{
...
struct Result: public TypesafeEnum
{
static const Result CANCEL("Cancel");
static const Result OK("Ok");
};
Result doModal();
...
};
const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;
Addition:
I think I should have been more specific about the requirements. I'll try to summarize them:
Priority 1: Setting an enum variable to an invalid value should be impossible (a compile-time error) with no exceptions.
Priority 2: Converting an enum value to/from an int should be possible with a single explicit function/method call.
Priority 3: As compact, elegant and convenient declaration and usage as possible
Priority 4: Converting enum values to and from strings.
Priority 5: (Nice to have) Possibility to iterate over enum values.
I'm currently playing around with the Boost.Enum proposal from the Boost Vault (filename enum_rev4.6.zip). Although it was never officially submitted for inclusion into Boost, it's useable as-is. (Documentation is lacking but is made up for by clear source code and good tests.)
Boost.Enum lets you declare an enum like this:
BOOST_ENUM_VALUES(Level, const char*,
(Abort)("unrecoverable problem")
(Error)("recoverable problem")
(Alert)("unexpected behavior")
(Info) ("expected behavior")
(Trace)("normal flow of execution")
(Debug)("detailed object state listings")
)
And have it automatically expand to this:
class Level : public boost::detail::enum_base<Level, string>
{
public:
enum domain
{
Abort,
Error,
Alert,
Info,
Trace,
Debug,
};
BOOST_STATIC_CONSTANT(index_type, size = 6);
Level() {}
Level(domain index) : boost::detail::enum_base<Level, string>(index) {}
typedef boost::optional<Level> optional;
static optional get_by_name(const char* str)
{
if(strcmp(str, "Abort") == 0) return optional(Abort);
if(strcmp(str, "Error") == 0) return optional(Error);
if(strcmp(str, "Alert") == 0) return optional(Alert);
if(strcmp(str, "Info") == 0) return optional(Info);
if(strcmp(str, "Trace") == 0) return optional(Trace);
if(strcmp(str, "Debug") == 0) return optional(Debug);
return optional();
}
private:
friend class boost::detail::enum_base<Level, string>;
static const char* names(domain index)
{
switch(index)
{
case Abort: return "Abort";
case Error: return "Error";
case Alert: return "Alert";
case Info: return "Info";
case Trace: return "Trace";
case Debug: return "Debug";
default: return NULL;
}
}
typedef boost::optional<value_type> optional_value;
static optional_value values(domain index)
{
switch(index)
{
case Abort: return optional_value("unrecoverable problem");
case Error: return optional_value("recoverable problem");
case Alert: return optional_value("unexpected behavior");
case Info: return optional_value("expected behavior");
case Trace: return optional_value("normal flow of execution");
case Debug: return optional_value("detailed object state listings");
default: return optional_value();
}
}
};
It satisfies all five of the priorities which you list.
A nice compromise method is this:
struct Flintstones {
enum E {
Fred,
Barney,
Wilma
};
};
Flintstones::E fred = Flintstones::Fred;
Flintstones::E barney = Flintstones::Barney;
It's not typesafe in the same sense that your version is, but the usage is nicer than standard enums, and you can still take advantage of integer conversion when you need it.
I use C++0x typesafe enums. I use some helper template/macros that provide the to/from string functionality.
enum class Result { Ok, Cancel};
I don't. Way too much overhead for little benefit. Also, being able to caste enumerations to different data types for serialization is a very handy tool. I have never seen an instance where a "Type safe" enumeration would be worth the overhead and complexity where C++ offers a good enough implementation already.
My take is that you're inventing a problem and then fitting a solution onto it. I see no need to do an elaborate framework for an enumeration of values. If you are dedicated to having your values only be members of a certain set, you could hack up a variant of a unique set datatype.
I'm personally using an adapted version of the typesafe enum idiom. It doesn't provide all the five "requirements" that you've stated in your edit, but I strongly disagree with some of them anyway. For example, I don't see how Prio#4 (conversion of values to strings) has anything to do with type safety. Most of the time string representation of individual values should be separate from the definition of the type anyway (think i18n for a simple reason why). Prio#5 (iteratio, which is optional) is one of the nicest things I'd like to see naturally happening in enums, so I felt sad that it appears as "optional" in your request, but it seems it is better addressed via a separate iteration system such as begin/end functions or an enum_iterator, which makes them work seamlessly with STL and C++11 foreach.
OTOH this simple idiom nicely provides Prio#3 Prio#1 thanks to the fact that it mostly only wraps enums with more type information. Not to mention it is a very simple solution that for the most part doesn't require any external dependency headers, so it's pretty easy to carry around. It also has the advantage of making enumerations scoped a-la-C++11:
// This doesn't compile, and if it did it wouldn't work anyway
enum colors { salmon, .... };
enum fishes { salmon, .... };
// This, however, works seamlessly.
struct colors_def { enum type { salmon, .... }; };
struct fishes_def { enum type { salmon, .... }; };
typedef typesafe_enum<colors_def> colors;
typedef typesafe_enum<fishes_def> fishes;
The only "hole" that solution provides is that it doesn't address the fact that it doesn't prevent enums of different types (or an enum and an int) from being directly compared, because when you use values directly you force the implicit conversion to int:
if (colors::salmon == fishes::salmon) { .../* Ooops! */... }
But so far I've found such problems can be solved by simply offering a better comparison to the compiler - for example, explicitly providing an operator that compares any two different enum types, then forcing it to fail:
// I'm using backports of C++11 utilities like static_assert and enable_if
template <typename Enum1, typename Enum2>
typename enable_if< (is_enum<Enum1>::value && is_enum<Enum2>::value) && (false == is_same<Enum1,Enum2>::value) , bool >
::type operator== (Enum1, Enum2) {
static_assert (false, "Comparing enumerations of different types!");
}
Though it doesn't seem to break code so far, and it does to explicitly deal with the specific problem without doing something else, I'm not sure it such thing is a thing one "should" do (I suspect it will interfere with enums already taking part in conversion operators declared elsewhere; I'd gladly receive commentary about this).
Combining this with the above typesafe idiom gives something that is relatively close to C++11 enum class in humanibility (readability and maintainability) without having to do anything too obscure. And I have to admit it was fun to do, I had never thought to actually ask the compiler if I was dealing with enums or not...
I think the Java enum would be a good model to follow. Essentially, the Java form would look like this:
public enum Result {
OK("OK"), CANCEL("Cancel");
private final String name;
Result(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
What's interesting about the Java approach is that OK and CANCEL are immutable, singleton instances of Result (with the methods that you see). You cannot create any further instances of Result. Since they're singletons, you can compare by pointer/reference---very handy. :-)
ETA: In Java, instead of doing bitmasks by hand, instead you use an EnumSet to specify a bit set (it implements the Set interface, and works like sets---but implemented using bitmasks). Much more readable than hand-written bitmask manipulation!
I gave an answer to this here, on a different topic. It's a different style of approach which allows most of the same functionality without requiring modification to the original enum definition (and consequently allowing usage in cases where you don't define the enum). It also allows runtime range checking.
The downside of my approach is that it doesn't programmatically enforce the coupling between the enum and the helper class, so they have to be updated in parallel. It works for me, but YMMV.
I am currently writing my own typesafe enum library at https://bitbucket.org/chopsii/typesafe-enums
I am not the most experienced C++ developer ever, but I am writing this due to the shortcomings of the BOOST vault enums.
Feel free to check it out and use them yourself, but they have some (hopefully minor) usability issues, and are probably not at all cross-platform.
Please contribute if you want to. This is my first open source undertaking.
Use boost::variant!
After trying a lot of the above ideas and finding them lacking I hit upon this simple approach:
#include <iostream>
#include <boost/variant.hpp>
struct A_t {};
static const A_t A = A_t();
template <typename T>
bool isA(const T & x) { if(boost::get<A_t>(&x)) return true; return false; }
struct B_t {};
static const B_t B = B_t();
template <typename T>
bool isB(const T & x) { if(boost::get<B_t>(&x)) return true; return false; }
struct C_t {};
static const C_t C = C_t();
template <typename T>
bool isC(const T & x) { if(boost::get<C_t>(&x)) return true; return false; }
typedef boost::variant<A_t, B_t> AB;
typedef boost::variant<B_t, C_t> BC;
void ab(const AB & e)
{
if(isA(e))
std::cerr << "A!" << std::endl;
if(isB(e))
std::cerr << "B!" << std::endl;
// ERROR:
// if(isC(e))
// std::cerr << "C!" << std::endl;
// ERROR:
// if(e == 0)
// std::cerr << "B!" << std::endl;
}
void bc(const BC & e)
{
// ERROR:
// if(isA(e))
// std::cerr << "A!" << std::endl;
if(isB(e))
std::cerr << "B!" << std::endl;
if(isC(e))
std::cerr << "C!" << std::endl;
}
int main() {
AB a;
a = A;
AB b;
b = B;
ab(a);
ab(b);
ab(A);
ab(B);
// ab(C); // ERROR
// bc(A); // ERROR
bc(B);
bc(C);
}
You can probably come up with a macro to generate the boilerplate. (Let me know if you do.)
Unlike other approaches this one is actually type-safe and works with old C++. You can even make cool types like boost::variant<int, A_t, B_t, boost::none>, for example, to represent a value that could be A, B, an integer or nothing which is almost Haskell98 levels of type safety.
Downsides to be aware of:
at-least with old boost -- I'm on a system with boost 1.33 -- you are limited to 20 items in your variant; there is a work-around however
affects compile time
insane error messages -- but that's C++ for you
Update
Here, for your convenience is your typesafe-enum "library". Paste this header:
#ifndef _TYPESAFE_ENUMS_H
#define _TYPESAFE_ENUMS_H
#include <string>
#include <boost/variant.hpp>
#define ITEM(NAME, VAL) \
struct NAME##_t { \
std::string toStr() const { return std::string( #NAME ); } \
int toInt() const { return VAL; } \
}; \
static const NAME##_t NAME = NAME##_t(); \
template <typename T> \
bool is##NAME(const T & x) { if(boost::get<NAME##_t>(&x)) return true; return false; } \
class toStr_visitor: public boost::static_visitor<std::string> {
public:
template<typename T>
std::string operator()(const T & a) const {
return a.toStr();
}
};
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
inline static
std::string toStr(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & a) {
return boost::apply_visitor(toStr_visitor(), a);
}
class toInt_visitor: public boost::static_visitor<int> {
public:
template<typename T>
int operator()(const T & a) const {
return a.toInt();
}
};
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
inline static
int toInt(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & a) {
return boost::apply_visitor(toInt_visitor(), a);
}
#define ENUM(...) \
typedef boost::variant<__VA_ARGS__>
#endif
And use it like:
ITEM(A, 0);
ITEM(B, 1);
ITEM(C, 2);
ENUM(A_t, B_t) AB;
ENUM(B_t, C_t) BC;
Notice you have to say A_t instead of A in the ENUM macro which destroys some of the magic. Oh well. Also, notice there's now a toStr function and a toInt function to meet OPs requirement of simple conversion to strings and ints. The requirement I can't figure out is a way to iterate over the items. Let me know if you know how to write such a thing.
Not sure if this post is too late, but there's an article on GameDev.net which satisfies all but the 5th point (ability to iterate over enumerators):
http://www.gamedev.net/reference/snippets/features/cppstringizing/
The method described by the article allows string conversion support for existing enumerations without changing their code. If you only want support for new enumerations though, I'd go with Boost.Enum (mentioned above).

Map C++ enums as const char*

I have the following enum and map:
typedef enum {
MaxX = 0,
MaxY,
MaxCells,
MaxCycles,
Threes
} SettingName;
typedef std::map<SettingName, const char*> SettingNameCollection;
SettingNameCollection settingNames;
And I have the following function to return the enum name:
const char* gofBoard::getSettingName(unsigned x) {
return settingNames[static_cast<SettingName>(x)];
}
And from what I've read that should work, but the function doesn't return anything. There's no compile time errors, and no runtime errors.
Here's my suggestion:
1- Write this macro:
#define SMART_STRINGIFY_CASE(ENUM_CODE) case ENUM_CODE: return # ENUM_CODE
2- Write this function:
const char* SettingNamesToString( settingNames const input)
{
switch(input)
{
SMART_STRINGIFY_CASE(MaxX);
SMART_STRINGIFY_CASE(MaxY);
...
default:
// your own !
}
The operator[] is used to retreive/insert data in a std::map. You might be more conformtable with std::map::find:
const char* gofBoard::getSettingName(unsigned x) {
auto found = settingNames.find(static_cast<SettingName>(x));
if (found == settingNames.end())
/* throw appropriate exception */
/* or assert */
assert ( found != settingNames.end() );
return found->second;
}
EDIT: like someone said, for your purpose, a simple std::array would be enough.
If you do not populate the map before you call that function, what you are getting isnt an error, its a blank string (im guessing)
You want to do something like this
typedef std::array<const char*,Threes+1> SettingNameCollection;
// usually for such purposes, sometimes an extra enum is added to give you number of valid enum values ( Settings_Num for instance)
SettingNameCollection settingNames {
"MaxX ",
.....
"Threes",
}; // first time using the new syntax, is this correct?
const char* gofBoard::getSettingName(SettingName setting) {
return settingNames[setting]; //do i need to cast to int in c++11?
}
A map is certainly overkill if your enum is contiguous. I would suggest switching to a macro definition.
Excerpt:
SANDBOX_DEFINE_ENUM(MyEnum, (Foo)(Bar)(Team))
Will expand to:
struct MyEnum {
enum Type {
Foo,
Bar,
Team
};
static Type const First = Foo;
static Type const Last = Team;
};
inline char const* toString(MyEnum::Type value) {
switch(value) {
case MyEnum::Foo: return "Foo";
case MyEnum::Bar: return "Bar";
case MyEnum::Team: return "Team";
}
return 0;
}
Everyone who programmed in C++ extensively has run into the problem of enum to string conversion (and string to enum conversion). There are various aspects to consider to solve the problem well, e.g. what if the string for an invalid enum is requested. I think you will benefit by using a generic solution that you can use for most or all of your enums. That problem is covered by this question:
Which Typesafe Enum in C++ Are You Using?

Whats the right approach to return error codes in C++

I'm using error codes for handling errors in my c++ project. The problem is how to return error codes from a function which is supposed to return some variable/object.
consider this:
long val = myobject.doSomething();
Here, myobject is an object of some class. If doSomething function encounters some error condition then how should it notify the caller (Without using exceptions).
Possible solutions:
Have a data member (say err_) in the class which can be checked by the caller. But it would be unsafe in a multi-threaded application sharing the same object and calling the same function.
Use some global error variable, again same issue in a multi-threaded environment.
Now how can I notify the caller about some error condition?
Make a template called, say, Maybe that it parametrized by your return value type. Whenever you return a value, wrap it in this template like this:
Maybe<long> result = object.somemethod();
The Maybe template would have a way of being instantiated with an error code (probably a static method):
return Maybe<long>::error(code);
But ordinarily would just be returned with the value:
Maybe<long> retval;
retval = 15;
return retval;
(You would have to, of course, override the appropriate constructors, assignment operators, etc.)
In the client side you call a method to check for the error.
Maybe<long> result = object.somemethod();
if (result.is_error)
{
... handle the error ...
}
else
{
... use the result ...
}
Again you'd need the appropriate operators defined to use Maybe<long> wherever there's a long required.
This sounds like a lot of work, but really the work is done once in making a good, bulletproof Maybe template. You'll also have to do some performance tuning on it to avoid nasty overheads. If you want to make it more flexible you can parametrize it on both the return value type and the error type. (This is only a minor increase in complexity.)
You probably want something like Alexandresu's Expected<T> idiom.
You can pass variable as reference and return error code in it.
You can return a std::pair holding both an error code (or error object) and the desired return object. The object of interest needs a default constructor or value so you can return something even when an error is encountered.
It is common to return a return/error code, and make available a property or member with the results.
int retCode = myobject.doSomething();
if (retCode < 0){ //Or whatever you error convention is
//Do error handling
}else{
long val = myobject.result;
}
It is also common to pass in a pointer that is set to the return value, and return the return/error code. (See HrQueryAllRows).
long val = INIT_VAL;
int retCode = myObject.doSomething(&val);
if (retCode < 0){
//Do error handling
}else{
//Do something with val...
}
You have three options:
Create a class containing the return value and a possible error code.
Use something like boost::optional for the return value, which allows
for invalid responses.
Pass a reference to a variable and return any possible error code
within that.
I see there are many nice solutions, but I approach it in another way if I have this situation.
auto doSomething()
{
// calculations
return std::make_pair(error_code, value)
}
int main()
{
auto result = doSomething();
if (!result.first)
{
std::cout << result.second;
}
else
{
std::cout << "Something went wrong: " << result.second;
}
}
For me it's a clean solution than passing bool as reference. auto return type deduction is supported from c++14
Return an error handle. Have an error manager keep the error codes and additional informations (e.g. ERROR_INVALID_PARAMETER and name-value-pairs like ParameterName="pszFileName"). This information can be accessed using the handle. The caller can check the error handle against a NO_ERROR_HANDLE. If true, no error occurred. The caller can augment the error information and pass the handle up the stack.
The error manager can be one for the process or one for each thread.
I would suggest following:
class foo {
public:
long doSomething();
long doSomething(error_code &e);
};
Where error_code is some type that holds error. It may be integer or better something based on boost::system::error_code.
And you supply two functions:
First version throws the error, for example throw boost::system::system_error that is created from boost::system::error_code.
Second returns the error code into e.
The most common practice is to return the error code
long result;
int error = some_obj.SomeMethod(&result);
or return a value that indicate there was an error:
long result = some_obj.SomeMethod();
if (result < 0) error = some_obj.GetError();
In C++17 you use std::optional from the <optional> header:
std::optional<long> myobject = some_func(some_bool);
if (myobject.has_value()) {
// do stuff with myobject.value()
} else {
// myobject has no value
}
// ...
// Example function that returns an optional
std::optional<long> some_func(bool b) {
if (b)
return 15;
return {};
}
define all the error codes in a File. based on error category you can return the error code and the caller can decide what went wrong and caller can return its own error code.
for example
#define FILE_ERROR 1
#define SANITY_ERROR 2
int WriteToFile(char* Data, int iErrorCode)
{
char* FileName;
if (!FileOpen(FileName, &iErrorCode))
{
//Analyze error code and make decision on what to ignore or terminate
iErrorCode = FILE_ERROR;
return 0;
}
}
int FileOpen(char* FileName, int* iErrorCode)
{
if (FileName == null)
{
iErrorCode = SANITY_ERROR;
return 0;
}
///// next code blocks
return 1;
}
I found a new way to do it. It is non-standard and this is an entirely new way to do it.
So consider using this approach cautiously.
Use the following header file:
SetError.h:
#include <string> // for string class
#ifndef SET_ERROR_IS_DEFINED
#define SET_ERROR_IS_DEFINED
class Error {
public:
int code = 0;
std::string errorMessage;
std::string fileName;
std::string functionName;
Error() {}
Error(int _errorCode, std::string _functionName = "", std::string _errorMessage = "", std::string _fileName = "")
{
code = _errorCode;
functionName = _functionName;
errorMessage = _errorMessage;
fileName = _fileName;
}
};
#if defined(_DEBUG) || !defined(NDEBUG)
#define ___try { _ERROR.code = 0; bool __valid_try_mode_declared;
#define ___success }
#define SetError(pErrorData) __valid_try_mode_declared = true; _ERROR = *pErrorData; delete pErrorData;
#else
#define ___try { _ERROR.code = 0;
#define ___success }
#define SetError(pErrorData) _ERROR = *pErrorData; delete pErrorData;
#endif
#endif
inline Error _ERROR;
Include it everyware.
Example of how to use:
Main.cpp:
#include "SetError.h"
#include <iostream>
bool SomeFunction(int value) ___try;
{
if (value < 0) {
SetError(new Error(10, "SomeFunction", "Some error", "File main.cpp"));
return false;
}
return true;
} ___success; // You mast to warp the function with both ___try and ___success
// These keywords must be at the start and the end of the function!
int main()
{
using namespace std;
bool output = SomeFunction(-1);
if (_ERROR.code != 0) { // This is how you check the error code. using the global _ERROR object
cout << "error code: " << _ERROR.code << ", from function: "
<< _ERROR.functionName << ", from file: " << _ERROR.fileName;
}
cout << endl << "Founction returned: " << output << endl;
return 1;
}
If you have some functions that run in another thread, these functions need to be inside namespace and then you can do this:
namespace FunctionsInSomeThread
{
#include "SetError.h"
bool SomeFunc1() ___try;
{
SetError(new Error(5, "SomeFunction2", "Some error from another thread", "File main.cpp"))
return true;
} ___success;
bool SomeFunc2() ___try;
{
SetError(new Error(5, "SomeFunction2", "Some error from another thread", "File main.cpp"))
return true;
} ___success;
}
And to access _Error, you need to add the namespace of the thread
if (FunctionsInSomeThread::_ERROR.code != 0)
{
// Error handling
}
Or in case it is inside the same namespace then no need to add FunctionsInSomeThread:: before.
The idea behind this is that you can't warp the function only with ___success; keyword. You will get compile error. So the developer will never return old error code from another function.
If you wrote ___success; at the end of the codeblock, you must write also ___try; at the start!
You also can't use SetError macro if it is not wrapped in ___try; and ___success;.
The idea come from the AutoIt language where you have this consept:
https://www.autoitscript.com/autoit3/docs/functions/SetError.htm
So this is almost the same in C if you use this header.