At a previous employer, we were writing binary messages that had to go "over the wire" to other computers. Each message had a standard header something like:
class Header
{
int type;
int payloadLength;
};
All of the data was contiguous (header, immediately followed by data). We wanted to get to the payload given that we had a pointer to a header. Traditionally, you might say something like:
char* Header::GetPayload()
{
return ((char*) &payloadLength) + sizeof(payloadLength);
}
or even:
char* Header::GetPayload()
{
return ((char*) this) + sizeof(Header);
}
That seemed kind of verbose, so I came up with:
char* Header::GetPayload()
{
return (char*) &this[1];
}
It seems rather disturbing at first, possibly too odd to use -- but very compact.
There was a lot of debate on whether it was brilliant or an abomination.
So which is it - Crime against coding, or nice solution? Have you ever had a similar trade-off?
-Update:
We did try the zero sized array, but at the time, compilers gave warnings.
We eventually went to the inhertited technique: Message derives from Header.
It works great in practice, but in priciple you are saying a message IsA Header - which seems a little awkward.
I'd go for crime against coding.
Both methods will generate the exact same object code. The first makes it's intention clear. The second is very confusing, with the only advantage that it saves a couple keystrokes. (Just learn to freakin' type).
Also, note that NEITHER method is guaranteed to work. The sizeof() an object includes padding for word alignment, so that if the header was:
class Header
{
int type;
int payloadLength;
char status;
};
Both methods you describe would have the payload starting at Header+12, when most likely it actually starts at Header+9.
You're depending on the compiler to layout your classes in a particular way. I would have defined the message as a struct (with me defining layout) and had a class that encapsulates the message and provides the interface to it. Clear code = good code. "Cute" code = bad (hard to maintain) code.
struct Header
{
int type;
int payloadlength;
}
struct MessageBuffer
{
struct Header header;
char[MAXSIZE] payload;
}
class Message
{
private:
MessageBuffer m;
public:
Message( MessageBuffer buf ) { m = buf; }
struct Header GetHeader( )
{
return m.header;
}
char* GetPayLoad( )
{
return &m.payload;
}
}
It's been awhile since I've written any C++, so please excuse any issues with syntax. Just trying to convey the general idea.
Personally I think that if there's a crime, it's asking the header for the payload.
But as long as you're going to do it that way, 'this+1' is as good a way as any.
Justification: '&this[1]' is a general-purpose piece of code that doesn't require you to go digging through class-definitions to fully comprehend, and doesn't require fixing when someone changes the name or contents of the class.
BTW, the first example is the true crime against humanity. Add a member to the end of the class and it'll fail. Move the members around the class and it'll fail. If the compiler pads the class, it'll fail.
Also, if you're going to assume that the compiler's layout of classes/structs matches your packet layout, then you should understand how the compiler in question works. Eg. on MSVC you'll probably want to know about #pragma pack.
PS: It's a little scary how many people consider "this+1" or "&this[1]" hard to read or understand.
It's a common problem, but what you actually want is this.
class Header
{
int type;
int payloadLength;
char payload[0];
};
char* Header::GetPayload()
{
return payload;
}
My vote is Coding Horror. Don't get me wrong, it's clever - but you're saving yourself one entire addition operation at the cost of making the code much more difficult to understand and read. I don't see the tradeoff as worth it.
I think this is flawed from the start on if the header needs to "return" data which is not included in it.
As you already put yourself on these hackish grounds, I really love what you came up with.
But note that this is not a beauty contest. You should find an entire different solution. For alle the three versions of GetPayload() you presented, I would not understand what the hell is going on there without your further explanation.
Have you considered the 'empty array member' trick? I remember seeing it often, and even using it once or twice, but I can't seem to find any really good references (except, maybe, the one referenced below).
The trick is to declare your struct as
struct bla {
int i;
int j;
char data[0];
}
Then, the 'data' member simply points to whatever is behind the headers. I am not sure how portable this is; I've seen it with '1' as the array size as well.
(using the URL below as a referece, using the '[1]' syntax, seemed not to work because it is too long. Here is the link:)
http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/gcc/Zero-Length.html
If it works -- consistently -- then it's an elegant solution.
It will normally work in memory because the compiler will deal with alignment issues and you can assume that the Payload follows the header in correctly-aligned memory space.
I could see this falling apart when the Header/Payload objects are streamed "over the wire" because the streaming mechanism you use will probably not care about aligning objects on any particular boundary. Therefore, Payload may directly follow the Header with no padding to force it to a particular alignment.
To coin a phrase, elegant is as elegant does. So, it's elegant as long as you are careful how you stream it.
First, there's an awful lot of space between "crime against coding" and "nice solution," but I'd say this is closer to the former.
Is the Header its Payload's keeper?
That's the fundamental problem here -- both the header and the payload should be managed by another object that holds the entire message, and that is the proper place to ask for the payload. And it would be able to do so without pointer arithmetic or indexing.
Given that, I would favor the second solution, since it is clearer what is going on.
But that we're in this situation to begin with seems to indicate that the culture of your team values cleverness over clarity, so I guess all bets are off.
If you really want to be cute, you could generalize.
template<typename T. typename RetType>
RetType JustPast(const T* pHeader)
{
return reinterpret_cast<RetType>(pHeader + sizeof(T));
}
They're basically the same thing as far as I'm concerned. Both are forms of byte juggling, which is always risky, but not impossible to get right.
The first form is a bit more accepted and recognizable.
I would personally write :
char* Header::GetPayload()
{
return ((char*) this) + sizeof(*this);
}
Don't forget that VC++ may impose a padding on the sizeof() value on the class. Since the provided example is expected to be 8 bytes, it is automatically DWORD aligned, so should be ok. Check #pragma pack.
Though, I agree, the provided examples are some degree of Coding Horror. Many Win32 data structures include a pointer placeholder in the header structure when variable length data follows. This is probably the easiest way to reference this data once it's loaded into memory. The MAPI SRowSet structure is one example of this approach.
I actually do something similar, and so does nearly every MMO or online video game ever written. Although they have a concept called a "Packet" and each packet has it's own layout. So you might have:
struct header
{
short id;
short size;
}
struct foo
{
header hd;
short hit_points;
}
short get_foo_data(char *packet)
{
return reinterpret_cast<foo*>(packet)->hit_points;
}
void handle_packet(char *packet)
{
header *hd = reinterpret_cast<header*>(packet);
switch(hd->id)
{
case FOO_PACKET_ID:
short val = get_foo_data(packet);
//snip
}
}
And they do that for the majority of their packets. Some packets obviously have dynamic sizes, and for those members they use length prefixed fields and some logic to parse that data.
I think in this day and age, in C++, the C-style cast to char* disqualifies you from any "brilliant design idea" awards without getting much of a hearing.
I might go for:
#include <stdint.h>
#include <arpa/inet.h>
class Header {
private:
uint32_t type;
uint32_t payloadlength;
public:
uint32_t getType() { return ntohl(type); }
uint32_t getPayloadLength() { return ntohl(payloadlength); }
};
class Message {
private:
Header head;
char payload[1]; /* or maybe std::vector<char>: see below */
public:
uint32_t getType() { return head.getType(); }
uint32_t getPayloadLength() { return head.getPayloadLength(); }
const char *getPayload() { return payload; }
};
This assumes C99-ish POSIX, of course: to port to non-POSIX platforms you'd have to define one or both of uint32_t and ntohl yourself, in terms of whatever the platform does offer. It's usually not hard.
In theory you might need layout pragmas in both classes. In practice I'd be surprised given the actual fields in this case. The issue can be avoided by reading/writing the data from/to iostreams one field at a time, rather than trying to construct the bytes of the message in memory and then write it in one go. It also means you can represent the payload with something more helpful than a char[], which in turn means you won't need to have a maximum message size, or mess about with malloc and/or placement new, or whatever. Of course it introduces a bit of overhead.
Perhaps you should have used a verbose method, but replaced it with a #define macro? This way you can use your shorthand when typing, but anyone needing to debug the code can follow along without issue.
I vote for &this[1]. I've seen it used quite a bit when parsing files that have been loaded into memory (which can equally include received packets). It may look a tad odd the first time you see it, but I think that what it means should be immediately obvious: it's clearly the address of memory just past this object. It's nice because it's hard to get wrong.
I don't like to use words like "crime". I would rather point out that &this[1] seems to make assumptions about memory layout that a compiler might disagree with. For example, any compiler might, for its own reasons (like alignment), insert dummy bytes anywhere in a structure. I would prefer a technique that has more of a guarantee of getting the correct offset if compilers or options get changed.
In addition to the abovementioned, I'd say that this is a crime against interoperability and good wire protocol design principles. It is really surprising how many programmers are not able/willing to make a clear distinction between a wire protocol definition and its implementation.
If your protocol has to survive for more than two days, it most probably has to survive for more than two years/OSes/compilers/languages/endiannesses and in some point it will break, rather sooner than later. So, make other folks' life easier, write down the wire protocol specification plus write proper (de)serialization routines. Otherwise, people will keep mentioning your name in not so pleasant contexts.
Related
I'm implementing a helper class which has a number of useful functions which will be used in a large number of classes. However, a few of them are not designed to be called from within certain sections of code (from interrupt functions, this is an embedded project).
However, for users of this class the reasons why some functions are allowed while others are prohibited from being called from interrupt functions might not be immediately obvious, and in many cases the prohibited functions might work but can cause very subtle and hard to find bugs later on.
The best solution for me would be to cause a compiler error if the offending function is called from a code section it shouldn't be called from.
I've also considered a few non-technical solutions, but a technical one would be preferred.
Indicate it in the documentation with a warning. Might be easily missed, especially when the function seems obvious, like read_byte(), why would anyone study the documentation whether the function is reentrant or not?
Indicate it in the function's name. Ugly. Who likes function names like read_byte_DO_NOT_CALL_FROM_INTERRUPT() ?
Have a global variable in a common header, included in each and every file, which is set to true at the beginning of each interrupt, set to false at the end, and the offending functions check it at their beginning, and exit if it's set. Problem: interrupts might interrupt each other. Also, it doesn't cause compile-time warnings or errors.
Similar to #3, have a global handler with a stack, so that nested interrupts can be handled. Still has the problem of only working at runtime and it also adds a lot of overhead. Interrupts should not waste more than a clock cycle or two for this feature, if at all.
Abusing the preprocessor. Unfortunately, the naive way of a #define at the beginning and an #undef at the end of each interrupt, with an #ifdef at the beginning of the offending function doesn't work, because the preprocessor doesn't care about scope.
As interrupts are always classless functions, I could make the offending functions protected, and declare them as friends in all classes which use them. This way, it would be impossible to use them directly from within interrupts. As main() is classless, I'll have to place most of it into a class method. I don't like this too much, as it can become needlessly complicated, and the error it generates is not obvious (so users of this function might encapsulate them to "solve" the problem, without realizing what the real problem was). A compiler or linker error message like "ERROR: function_name() is not to be used from within an interrupt" would be much more preferable.
Checking the interrupt registers within the function has several issues. In a large microcontroller there are a lot of registers to check. Also, there is a very small but dangerous chance of a false positive when an interrupt flag is being set exactly one clock cycle before, so my function would fail because it thinks it was called from an interrupt, while the interrupt would be called in the next cycle. Also, in nested interrupts, the interrupt flags are cleared, causing a false negative. And finally, this is yet another runtime solution.
I did play with some very basic template metaprogramming a while ago, but I'm not that experienced with it to find a very simple and elegant solution. I would rather try other ways before committing myself to try to implement a template metaprogramming bloatware.
A solution working with only features available in C would also be acceptable, even preferable.
Some comments below. As a warning, they won't be fun reading, but I won't do you a service by not pointing out what's wrong here.
If you are calling external functions from inside an ISR, no amount of documentation or coding will help you. Since in most cases, it is bad practice to do so. The programmer must know what they are doing, or no amount of documentation or coding mechanisms will save the program.
Programmers do not design library functions specifically for the purpose of getting called from inside an ISR. Rather, programmers design ISR:s with all the special restrictions that come with an ISR in mind: make sure interrupt flags are cleared correctly, keep the code short, do not call external functions, do not block the MCU longer than necessary, consider re-entrancy, consider dangerous compiler optimizations (use volatile). A person who does not know this is not competent enough to write ISRs.
If you actually have a function int read_byte(int address) then this suggests that the program design is bad to begin with. This function could do one of two things:
Either it can read a byte some some peripheral hardware, in which case the function name is very bad and should be changed.
Or it could read any generic byte from an address, in which case the function is 100% useless "bloatware". You can safely assume that a somewhat competent C programmer can read a byte from a memory address without some bloatware holding their hand.
In either case, int is not a byte. It is a word of 16 or 32 bits. The function should be returning uint8_t. Similarly, if the parameter passed is used to descibe a memory-mapped address of an MCU, it should either have type void*, uint8_t* or uintptr_t. Everything else is wrong.
Notably, if you are using int rather than stdint.h for embedded systems programming, then this whole discussion is the least of your problems, as you haven't even gotten the fundamental basics right. Your programs will be filled to the brim with undefined behavior and implicit promotion bugs.
Overall, all the solutions you suggest are simply not acceptable. The root of the problem here appears to be the program design. Deal with that instead of inventing ways to defend the broken design with horrible meta programming.
I would suggest option 8 & 9.
Peer reviews & assertions.
You state in the comments that your interrupt functions are short. If that's really the case, then reviewing them will be trivial. Adding comments in the header will make it so that anyone can see what's going on. On adding an assert, while you make it viable that debug builds will return the wrong result in error, it will also ensure that you you will catch any calls; and give you a fighting chance during testing to catch the problem.
Ultimately, the macro processing just won't work since the best you can do is catch if a header has been included, but if the callstack goes via another wrapper (that doesn't have comments) then you just can't catch that.
Alternatively you could make your helper a template, but then that would mean every wrapper around your helper would also have to be a template so that can know if you're in an interrupt routine... which will ultimately be your entire code base.
if you have one file for all interrupt routine then this might be helpful:
define one macro in class header ,say FORBID_INTERRUPT_ROUTINE_ACCESS.
and in interrupt handler file check for that macro definition :
#ifdef FORBID_INTERRUPT_ROUTINE_ACCESS
#error : cannot access function from interrupt handlers.
#endif
if someone add header file for that class to use that class in interrupt handler then it will throw an error.
Note : you have to build target by specifying that warnings will be considered as error.
Here is the C++ template functions suggestion.
I don't think this is metaprogramming or bloatware.
First make 2 classes which will define the context which the user will be using the functions in:
class In_Interrupt_Handler;
class In_Non_Interrupt_Handler;
If You will have some common implementations between the 2 contexts, a Base class can be added:
class Handy_Base
{
protected:
static int Handy_protected() { return 0; }
public:
static int Handy_public() { return 0; }
};
The primary template definition, without any implementations. The implemenations will be provided by the specialization classes:
template< class Is_Interrupt_Handler >
class Handy_functions;
And the specializations.
// Functions can be used when inside an interrupt handler
template<>
struct Handy_functions< In_Interrupt_Handler >
: Handy_Base
{
static int Handy1() { return 1; }
static int Handy2() { return 2; }
};
// Functions can be used when inside any function
template<>
struct Handy_functions< In_Non_Interrupt_Handler >
: Handy_Base
{
static int Handy1() { return 4; }
static int Handy2() { return 8; }
};
In this way if the user of the API wants to access the functions, the only way is by specifing what type of functions are needed.
Example of usage:
int main()
{
using IH_funcs = Handy_functions<In_Interrupt_Handler>;
std::cout << IH_funcs::Handy1() << '\n';
std::cout << IH_funcs::Handy2() << '\n';
using Non_IH_funcs = Handy_functions<In_Non_Interrupt_Handler>;
std::cout << Non_IH_funcs::Handy1() << '\n';
std::cout << Non_IH_funcs::Handy2() << '\n';
}
In the end I think the problem boils down to the developer using Your framework. And How much Your framework requires the devloper to boilerplate.
The above does not stop the developer calling the Non Interrupt Handler functions from inside an Interrupt Handler.
I think that type of analysis would require some type of static analysis checking system.
Suppose there are 30 numbers I had to input into an executable, because of the large amount of input, it is not reasonable to input them via command line. One standard way is to save them into a single XML file and use XML parser like tinyxml2 to parse them. The problem is if I use tinyxml2 to parse the input directly I will have a very bloated main function, which seems to contradict the common good practice.
For example:
int main(int argc, char **argv){
int a[30];
tinyxml2::XMLDocument doc_xml;
if (doc_xml.LoadFile(argv[1])){
std::cerr << "failed to load input file";
}
else {
tinyxml2::XMLHandle xml(&doc_xml);
tinyxml2::XMLHandle a0_xml =
xml.FirstChildElement("INPUT").FirstChildElement("A0");
if (a0_xml.ToElement()) {
a0_xml.ToElement()->QueryIntText(&a[0]);
}
else {
std::cerr << "A0 missing";
}
tinyxml2::XMLHandle a1_xml =
xml.FirstChildElement("INPUT").FirstChildElement("A1");
if (a1_xml.ToElement()) {
a1_xml.ToElement()->QueryIntText(&a[1]);
}
else {
std::cerr << "A1 missing";
}
// parsing all the way to A29 ...
}
// do something with a
return 0;
}
But on the other hand, if I write an extra class just to parse these specific type of input in order to shorten the main function, it doesn't seem to be right either, because this extra class will be useless unless it's used in conjunction with this main function since it can't be reused elsewhere.
int main(int argc, char **argv){
int a[30];
ParseXMLJustForThisExeClass ParseXMLJustForThisExeClass_obj;
ParseXMLJustForThisExeClass_obj.Run(argv[1], a);
// do something with a
return 0;
}
What is the best way to deal with it?
Note, besides reading XML files you can also pass lots of data through stdin. It's pretty common practice to use e.g. mycomplexcmd | hexdump -C, where hexdump is reading from stdin through the pipe.
Now up to the rest of the question: there's a reason to go with the your multiple-functions example (here it's not very important whether they're constructors or usual functions). It's pretty much the same as why would you want any function to be smaller — readability. That said, I don't know about the "common good practice", and I've seen many terminal utilities with very big main().
Imagine someone new is reading 1-st variant of main(). They'd be going through the hoops of figuring out all these handles, queries, children, parents — when all they wanted is to just look at the part after // do something with a. It's because they don't know if it's relevant to their problem or not. But in the 2-nd variant they'll quickly figure it out "Aha, it's the parsing logic, it's not what I am looking for".
That said, of course you can break the logic with detailed comments. But now imagine something went wrong, someone is debugging the code, and they pinned down the problem to this function (alright, it's funny given the function is main(), maybe they just started debugging). The bug turned out to be very subtle, unclear, and one is checking everything in the function. Now, because you're dealing with mutable language, you'd often find yourself in situation where you think "oh, may be it's something with this variable, where it's being changed?"; and you first look up every use of the variable through this large function, then conditions that could lead to blocks where it's changed; then you figuring out what does this another big block, relevant to the condition, that could've been extracted to a separate function, what variables are used in there; and to the moment you figured out what it's doing you already forgot half of what you were looking before!
Of course sometimes big functions are unavoidable. But if you asked the question, it's probably not your case.
Rule of thumb: you see a function doing two different things having little in common, you want to break it to 2 separate functions. In your case it's parsing XML and "doing something with a". Though if that 2-nd part is a few lines, probably not worth extracting — speculate a bit. Don't worry about the overhead, compilers are good at optimizing. You can either use LTO, or you can declare a function in .cpp file only as static (non-class static), and depending on optimization options a compiler may inline the code.
P.S.: you seem to be in the state where it's very useful to learn'n'play with some Haskell. You don't have to use it for real serious projects, but insights you'd get can be applied anywhere. It forces you into better design, in particular you'd quickly start feeling when it's necessary to break a function (aside of many other things).
I am relatively new to C++ - I leanerd it some 6+ years ago, but have never really used it until some months ago.
What is the scenario:
Considerably large system with a lot of modules.
Desired Output:
Modules (namely X) "expose" certain functions to be called over network and have the result sent back to the caller (namely Y)
The caller Y doesn´t know any info about X, despite what was exposed by the library (function name and parameters).
The calling of function in X from the library will have to happen through a string received from Y - or a set of strings, as there will be parameters as well.
Ideally what I want to have is something as generic as possible with variable return/paramaters types, or some kind of type-erasure - owing to the fact that I don´t know which functions each module will want to expose. I reckon its quite utopic to get something like that running in C++. But hopefully with pre-determined possible return/parameter types, it is feasible. The communication is not a problem for now, what matters is what should be done in the module side.
Question:
Would it be possible to accomplish such thing using C++ and Boost ? I would be really greateful if someone could give me some guidelines - literature/tutorials/(pseudo)code examples and so on and so forth. I am ofc not expecting a full solution here.
Possible solution:
I am a little bit lost as to which "functionalities" of the languages I can/should use - mainly due to my restrictions in the project.
I thought about using Variadic Templates and found the question below, which really helps, the only problem is that Variadic Templates are not supported in VS2010.
Generic functor for functions with any argument list
After some extensive research in the Web, the closest answer I got was this:
map of pointers to functions of different return types and signatures
The scenario is pretty much the same. The difference, however, seems to me that the OP already knows beforehand the return/parameters the functions he will be using. Due to my low reputation (I just joined) I unfortunately cannot ask/comment anything there.
TBH I didn´t get that well how to accomplish what the selected answer explains.
Using maps is a way, but I would have to store objects which contains function pointers (as also answered in the question), but as it is possible to see in the provided code by the user, it does have some hard-coded stuff which I wasn´t desiring to have.
Further clarifications:
Yes, I am restricted to use C++ AND VS2010 SP1.
No, despite Boost, I cannot use any other 3rd library - it would be great to be able to use some Reflection libraries such as CPGF http://www.cpgf.org/ (even though I am not 100% sure if thats what I really need)
Minor Edit:
- Scripting language bindings (such as LUA) are indeed a way to go, yet I didn´t want to include it in the project.
I hope someone can shed light on this problem!
Thanking in advance for any input!
Looks like you're needed a little reflection module. For example we have a struct of method info such as:
struct argument_info {
std::string name;
std::string type;
std::string value;
}
struct method_info {
std::string method_name;
std::string return_type;
std::list<argument_info> arguments;
}
then compile a dll with all exported functions
extern"C" __declspec(dllexport) void f1(int a, int b){/*...*/}
extern"C" __declspec(dllexport) int f1(std::string a, int b, char* c){ return x; }
in the interpreter's code:
void call_function(method_info mi, argument_info& t_return)
{
/* let g_mi be a map, where key is a std::string name of the method and the
value is method_info struct */
if(!g_mi->find(mi.method_name))
throw MethodNotFindException
if(g_mi[mi.method_name].arguments.size() != mi.arguments.size())
throw InvalidArgumentsCountException;
for(int i = 0; i < g_mi[mi.method_name].arguments.size(); i++)
{
if(g_mi[mi.method_name].arguments[i].type != mi.arguments[i].type)
throw InvalidArgumentException;
}
t_return = module->call(mi.arguments);
}
I hope it may help you.
I would like an opinion on what is the best way to handle static error strings in C++. I am currently using a number of constant char pointers, but they get unwieldy, and they are scatter every where in my code. Also should I be using static constant char pointers for these strings?
I was thinking about defines, hash tables, and INI files using the SimpleIni class for cross-platform compatibility. The project is an always running web server.
I would like to use error numbers or names to refer to them logically.
I am using the global space and methods contained in namespaced classes if that helps. The code is exported to C because of the environment if that helps as well.
Thanks
There are several things in tension here, so let me please enumerate them:
centralization / modularity: it is normal to think about centralizing things, as it allows to easily check for the kind of error one should expect and recover an error from an approximate souvenir etc... however modularity asks that each module be able to introduce its new errors
error may happen during dynamic initialization (unless you ban code from running then, not easy to check), to circumvent the lifetime issue, it is better to only rely on objects that will be initialized during static initialization (this is the case for string literals, for example)
In general, the simplest thing I have seen was to use some integral constant to identify an error and then have a table on the side in which you could retrieve other information (potentially a lot of it). For example, Clang uses this system for its diagnosis. You can avoid repeating yourself by using the preprocessor at your advantage.
Use such a header:
#define MYMODULE_ERROR_LIST \
ERROR(Code, "description") \
...
#define ERROR(Code, Desc) Code,
class enum ErrorCode: unsigned {
MYMODULE_ERROR_List
NumberOfElements
};
#undef ERROR
struct Error {
ErrorCode code;
char const* description;
};
Error const& error(ErrorCode ec);
And a simple source file to locate the array:
#define ERROR(Code, Desc) { Code, Desc },
Error const ErrorsArray[] = {
MYMODULE_ERROR_LIST
{ErrorCode::NumberOfElements, 0}
};
Error const& error(ErrorCode const ec) {
assert(unsigned(ec) < unsigned(ErrorCode::NumberOfElements) &&
"The error code must have been corrupted.");
return ErrorsArray[ec];
} // error
Note: the price of defining the macro in the header is that the slightest change of wording in a description implies a recompilation of all the code depending on the enum. Personally, my stuff builds much faster than its tested, so I don't care much.
This is quite an efficient scheme. As it respects DRY (Don't Repeat Yourself) it also ensures that the code-description mapping is accurate. The ERROR macro can be tweaked to have more information than just a description too (category, etc...). As long as the Error type is_trivially_constructible, the array can be initialized statically which avoids lifetime issues.
Unfortunately though, the enum is not so good at modularity; and having each module sporting its own enum can soon get boring when it comes to dealing uniformly with the errors (the Error struct could use an unsigned code;).
More involved mechanisms are required if you wish to get beyond a central repository, but since it seemd to suit you I'll stop at mentioning this limitation.
First of all, you can check other related questions on stackoverflow. Here you have some:
C++ Error Handling -- Good Sources of Example Code?
Exceptions and error codes: mixing them the right way
Then have a look at this great tutorial on error handling (it is a five parts tutorial, but you can access all of them from that link). This is especially interesting if you are using C++11, since it provides many more features for error handling. Alternatively you could use boost if you cannot use C++11.
You also need to consider whether you want to include support for localization. If your application may present messages to the users in different languages, it is better if you include that requirement from the very beginning in the error management too. You can check Boost.Locale for that, for instance.
I'd keep it simple, in a header:
enum ErrorCode { E_help, E_wtf, E_uhoh };
const char* errstr(ErrorCode);
Then in some .c or .cc file:
const char* error_strings[] = {
"help!",
"wtf?",
"uh-oh"
};
const char* errstr(ErrorCode e) { return error_strings[e]; }
Not a lot of detail in your question, but with what you've posted I would consider a singleton class for handling your error messages. You could create methods for accessing messages by code number or enum. Then you can implement internationalization or whatever else you need for your specific application. Also, if you do decide to use SQLite or some other file-based solution in the future, the class interface can remain intact (or be extended) minimizing impact on the rest of your code.
Rather simple question.
Where should I store error,exception, user messages?
By far, I always declared local strings inside the function where it is going to be invoked and did not bother.
e.g.
SomeClass::function1(...)
{
std::string str1("message1");
std::string str2("message2");
std::string str3("message3");
...
// some code
...
}
Suddenly I realized that since construction & initialization are called each time and it might be quite expensive. Would it be better to store them as static strings in class or even in a separate module?
Localization is not the case here.
Thanks in advance.
Why not just use a string constant when you need it?
SomeClass::function1(...)
{
/* ... */
throw std::runtime_error("The foo blortched the baz!");
/* ... */
}
Alternately, you can use static const std::strings. This is appropriate if you expect to copy them to a lot of other std::strings, and your C++ implementation does copy-on-write:
SomeClass::function1(...)
{
static const std::string str_quux("quux"); // initialized once, at program start
xyz.someMember = str_quux; // might not require an allocation+copy
}
If you expect to make lots of copies of these strings, and you don't have copy-on-write (or can't rely on it being present), you might want to look into using boost::flyweight.
TBH its probably best to ONLY construct error messages when they are needed (ie if something goes badly wrong who cares if you get a slowdown). If the messages are always going to appear then its probably best to define them statically to avoid the fact that they will be initialised each time. Generally, though, I only display user messages in debug mode so its quite easy to not show them if you are trying to do a performance build. I then only construct them when they are needed.