Valid
	XHTML 1.1! Valid CSS!
Created 2004-01-01   Modified 2009-04-11
Chelton Evans

proj Coding Conventions home

Intro
const variables declaration
Parameter Passing
Data Members In the Interface
Object Interfaces
Parameter Passing Versus Functions
Polluting the Name space
Understanding other Peoples Code
public, private, or protected?
Naming Variables
Placing Code in .h Files instead of .cpp Files
C is fast, C++ is faster in Theory
Functional Objects
Arrays and Vectors
Temporary Objects Instead of Static Functions
Name space Collisions
Macros
Error Strategy
Templates
Circular References
The Underscore Character
References
Issues

Intro

Coding conventions is a document that specifies the coding conventions. Traditionally it is rule based telling you what you can and can not do. For example when indenting use two spaces and no tab characters.

While there are a lot of rules here my source code is experimental. At times it is plain wrong and at others the ideas are in the process of evolving. As a consequence the rules are evolving over time.

The reason for the rule also needs to be explained. For example The Underscore Character states both the use and the reasoning behind the use. So this coding conventions document has these offside discussions to give meaning to the source code.

As a consequence this is not a rule based document, but aims to give more. I generally see the rules as conventions or guides.

While the interfaces are out there I rely on exact coding (use of const) for precision, and have strict guidelines on function signatures with const.

This development style is unique to my style of coding, but there is nothing to say that it could not be applied to large scale software development though the coding communities. The ideas have been formulated with discussions with other programmers. In particular as the program or product is often the blueprint for design removing artificial barriers to coding allows the programmer more options in development. I have written may classes that do not conform to information hiding principles that have stood the test of time, been robust and useful. Open interfaces applied this way are very powerful and contradict the information hiding way of thinking. I use both.

const variables declaration

I discuss the use of const for defining a const object. Then follow with a general discussion.

The most common way of using const in declarations is poor.

  const int i=3; // Poor programming style

Here is the way to do it.

  int const i=3; // Good programming style

When placing const on the rhs reading a declaration simply requires reading the expression from right to left. When const is placed on the lhs this no longer holds.

The consequence of the notation also effects typedefs and templates. These constructs use composite declarations. So placing const on the lhs breaks these because the compiler can not interpret the meaning of the expression because it changes after a substitution. This is not the case when const appears on the rhs - here the expression retains its meaning after a substitution and hence this type of declaration is critical for typedef and template use, see [1].

Now that I have got the technical arguments addressed, the real reason I like const on the rhs is that it makes declarations so much easier to read. While the example I gave was trivial it is not so for more complicated pointer expressions. I remember reading Kernigan and Richie's C and like a puzzle trying to work out some of their devilish declarations. However this technique completely solves the problem so that anyone can write or understand declarations. And when you start programming in the realm of templates then you will really appreciate how necessary this convention becomes - it is not optional!

Here is practical example with defining a pointer to a constant object where the pointer itself is constant. Note that the integer object itself need not be constant. Constance is about what the declaration will do to the object, not necessarily what the object is.

  int k(20);

  //const const int * p = & k;  // This will not compile.
  //const int * p const = & k;  // This will not compile.
  const int * const p = & k;
  int const * const p2 = & k;  // The best declaration.

  cout << *p << endl;
  cout << *p2 << endl;  

The first working declaration has const on the lhs for const int and then uses const on the rhs to get the pointer working, so it is having a go both ways. This is why the common practise is confusing.

int const * const p2 = & k; is read from right to left with no ambiguity. * const is the constant pointer. int const is the constant integer. Both statements place const before and on the rhs of the object being made const.

Here is another example with pointers to a function.

int const * ftemp(int const & x) { ... }

  int k=20;
  const int * p3;

  int const * (*pf)(int const & x);
  pf = & ftemp;
  p3 = (*pf)(k);
  cout << *p3 << endl;
  int const * (* const pf2)(int const & x) = & ftemp;
  p3 = (*pf2)(k);
  cout << *p3 << endl;

References are treated the same way as pointers. This code was easy to write, it compiled the first time.

Functions in classes can also be const as they do not modify the class when the function is called. While const data members in a class are boring const member functions can tell the client how to use the class. For example if you see a non const function when the programmer is using const rigorously then that function will change the objects state. So const plays the major role in interface designs.

While a temporary variable can subtly be used as a constant variable through the call to the copy constructor I prefer an explicit const declaration. For example
f4(bool & res, int a, int b)     becomes
f4(bool & res, int const a, int const b).
Now it becomes clear in the interface which are the const and non const variables.

Parameter Passing

The rule is simple. Make every variable that is input be declared as a const variable. All other non-const variables are output variables. Place the output variables at the start of the functions argument list.

This is a technique to pass data in and out of functions. It is disciplined programming because it relies on the programmer following the convention. The gain from this technique is that they can see at a glance what is going in and out of a function from the functions signature.

bool const foo
(
    double & x,
    int const id,
    string const & s
)

Input: id, s
Output: bool const
Output: Modified Variables: x

By looking at the interface we can see the input / output flow of the function.

Notice that the return value was made const too. The rule needed to treat the return value different from variables in the argument list. Without the function return value a non-const reference variable in the functions argument list would be used instead to return the result.

Additionally declaring the return value as const can prevent unfavorable type conversions.

The variables are separated into non-const and const groups. By convention, place the non-const at the start of the parameter signature. This has a magical effect of making the function signature more readable as you can immediately identify the input and output parameters. A small refinement was to place the const word on the right hand side of the variables type. This made the context clearer and meant the templates would not be confused as can happen when its placed on the left.

After years of C++ I believe the variables convention is the best change for writing good functions, many thanks to my former boss Nigel Stewart for realizing this convention.

The practice of using a variable for both input and output is a little confusing. For example you often have to read the documentation of the function to determine whether the variable is being written to or first read then written to. C often uses pointers so a variable is both an input and output.

C also does more typecasts and is weak in type safety so const appears to play a much less significant role in C than it does in C++. So I am not sure how useful having this parameter passing convention is to C programmers. In my opinion what C programmers only dream about can be done in C++ because you have both type safety and a clear sense of how functions input and output flow.

If a variable is both and input and output a self referencing situation can occur where the input is a const reference and is modified by writing to the output reference.

Depending on the context sometimes this is tested for but for normal everyday functions this is a wast of time. Generally we assume that the input and output variables are separate.

Object Interfaces

The interface to a class is the most important bit of code. Its the interface to the outside world, from a particular perspective.

Placing Code in .h Files instead of .cpp Files

When in Rome do what the Romans do - an English saying!

I used to place the declaration and definition in the header file. Separate the Interface from the Implementation by a comment. However since compilers do not support this model even if it is really easy to do so I have finally given in to pressure and will use the separate object linker model in the strict sense. i.e. all non-templated code goes into cpp files period.

However if ever I get a chair on the C++ committee - and do not hold your breath, I will push for source in one file, like Java. (For faster development time).

I am tired of arguing with the compiler and I want portable code. Its technically easy but philosophically that is not what people want. So if you run into some code that does this I am depreciating that style of code. The Romans win, me the barbarian looses - there is always next time.

template< typename T >
class menucallback : public menunode
{
  T & f;
public:

  menucallback( T & f_, string const & header )
    : menunode(header), f(f_) {}

  void writename()
    { f(this); }

  // Process a key from the keyboard.
  void eval(unsigned char const key)
    { if( ! f(this,key) ) menunode::eval(key); }
};

/*
 *---------------------------------------------------------------------
 * Implementation
 */

   ...

Implementation Code

For negative criticism and the reply see Polluting the Name Space .

For a few years I looked at my own interfaces with weirdness and frankly while I knew of a direction to head in I couldn't work out why. Why was I not following the object linker model and separating the C++ declaration from definition, instead stuffing things in the header file only.

Well after some reading I found the object-linker model to be a myth. Its impractical with templates and doesn't work with in line functions. Two of the biggest advances of C++. Plus the extra time involved cutting and pasting between two files (.h and .cpp). The latter is trivial compared with the former.

My solution was a pragmatic one - use the .h file only. Clearly comment the sections which are part of the implementation so there is a clear distinction between the interface and the implementation.

Note: the object .c and .cpp model is still important and can be adapted as is with in lining and templates where only whats needed is placed in the header and everything else goes into the cpp. However for the work I do I prefer not to argue with my compiler and just shove it in the header - a more natural solution.

Naming Variables

Sometimes people ask me whats the difference between C and C++ after I have said how much better C++ is.

To begin with often "good" C programmers have developed naming methodologies which have no language support. Sometimes what identifies them is at the start of the name, other times at the end, and other times not at all.

listPop
PopList
ListPop
...

C++ sort of solves this by putting the subject first.

list<int> L;
...
L.pop();

Structurally C++ is better for it and saves the energy of working out peoples weird naming conventions. However there will always be places for naming and I generally put the subject first because the subjects action is to generic. This way I just look at the start of the name and its immediately identified, and not looking at the end of the variable name.

With this discipline you will see other programming languages as a dogs breakfast. Which describes a lot of C.

C has no boundaries in the sense that this coding information is not part of the language. Where as objects (classes) are accessed in certain ways, the name is associated with the object in postfix sense.

So in naming policies I encourage myself to put the subject first, then the action.

Contrast this with the naming convention of the C++ casts where the action is first and the subject second.
{ dynamic_cast, static_cast, reinterpret_cast, const_cast }
With the subject first naming convention they would be called
{ cast_dynamic, cast_static, cast_reinterpret, cast_const }.

public, private, or protected?

My advise is to see someone else. However this is like a warranty disregarding any damage you are about to do after reading this as your own and continuing.

As much as I dislike Java it has these interface things which I do like. And as usual there is a technique for doing this anyway. By writing an interface class separate from the implementation class, a complicated class can be exposed for the interface class is written from its own perspective.

This is rather deep. My former boss wrote very good interfaces. In fact I have come to the conclusion that I will never be able to write interfaces like that. They both communicated how to be used and their use. These are really hard to write.

But I'm more complicated - I like extra functionality and directing the client to use an object in a particular way was not directly in my interest, but how could good classes be written like this?

By writing two classes with different perspectives is one technique for interfaces.

C++ provides const within the language. This can be used by the programmer to communicate which parts of the function/interface are variable and which are not - control that is not even dreamed about in C. This intern gives the programmer ability to write better interfaces because the client can see how a function is flowing.

Back again to access control. In networking its said that when you find yourself circumventing your own security to get things done then you probably have too much security. The same is true for access qualifiers.

If the interface class and main class are separated it does not make sense to protect functions in the main interface because they may be needed by the interface class - and I do not want anything to do with friends which complicate things.

Access qualifiers favor inheritance vs flat overloading hierarchies or functional objects or horizontal hierarchies as I like to call them. Because of this limitation I am against using access qualifiers, but when I do I find I am using inheritance often its with protected access.

Data members in the interface

This used to be a big no-no but I do not care. If putting data in the interface simplifies the situation I am in favor of it.

Time is precious and writing functions to access data can be taxing - say taxing because its an intellectual tax your paying, and yes it hurts.

This comes more into play with writing template code. Here minimalism is life and death. I have been caught out making the wrong data structure public but there's others that should be. The distinction between data and function has not got basis with composition. Here the data can be another subsystem, not data in the traditional sense of being operated on by functions, I leave such data to C programmers who because of their languages inabilities I conjecture that such biases arise. Note that although I believe in this if I was coding a commercial application I would follow the done method - except if I was going to get screwed doing it. Unfortunately its easy to get done on another's code.

Parameter Passing versus the use of a function returning a Temporary

TODO - rewrite

void f1(int & count, vector<int> & const v );
int const f1(vector<int> & const v );

The issue here is whether to use a functional form which could generate another temporary than necessary, or have the client supply the address for a direct write(no temporary if the client doesn't use one themselves).

Functions have two meanings, literally returning a value or doing something. Generally returning function values is inefficient - temporaries need to be constructed, copying, etc. It does however produce very readable code.

Writing code without functions that return values was done with parameter passing as described above. By passing a reference in the start of the argument sequence the function wrote to that memory location, so it places the emphasis of memory allocation to the client. In my integrator code this doubled the size of some in line functions that needed to call a function because temporaries needed to be constructed. Further without functions mathematical formulas look bulky and can't as easily be recognized for the mathematics that they are.

To address this I propose returning the first argument in the sequence when constructing a function that returns a value. The first argument must be a non-const reference. [Originally I rejected returning a user supplied reference because it meant that a variable had two return paths and how would the user know what was being returned? But for code readability and easier writing of maths routines I believe the rejection was an error.]

This convention is realized with ostream& << operator which returns ostream& .

Error Handling

Can use #ifdef directives to include and exclude debug code. The advantage is that the code is included for debugging and excluded from application for speed. The idea is that the errors are captured while debugging. Note that there is always the possibility that something could happen only in real time, but in practice almost any error in real time can be caught in debug code.

Place definition directive at top of file.
// Toggle debug
#define DEBUG_FILENAME

To turn on and of pieces of debug code, wrap them in if statements. For example.
#ifdef DEBUG_FILENAME
if (false)
{
code
}
#endif

The assert( true ); macro is by far the most useful error checking code, because if it fails the application halts till the condition is redressed.

Further you do not have to wrap it up. If N_DEBUG is defined the assert macro is not included in compilation and hence can be excluded from the release code. Have the <cassert> header before other headers.

Global Error Handling

As stated errors are captured in debug code and that code is excluded for the main application. Defining NDEBUG before #include <cassert> turns off the assert code altogether. By placing my local DEBUG_FILENAME within NDEBUG all the debug code can be turned off with NDEBUG.

#ifndef NDEBUG
//Toggle debug
#define DEBUG_FILENAME
#endif

Implement future error handling with this policy.

Directive Definitions

Minimize definitions outside the source, so the state of the application can be determined from the source code.

For example the debug code is included or excluded by commenting out the #define directive.

It may be worth while exploring makefiles to manage the applications options, building and executing. As directives can come through to the compiler as command line arguments.

Understanding other Peoples Code

This is perhaps the most single useful ability - to understand and fix someone else's code. I am not good at it, but by studying many things - computer science, hardware, mathematics, graphics, physics, ..., you will go along way.

Commenting out code segments, dating and putting a name and reason for commenting out code, plus source control doc is I believe the usual way for changing code. By leaving in the previous code you protect yourself - or leave a bigger mess.

Cleaning up code is as important as fixing it.

Polluting the Name space

Someone told me that by placing STL headers in .h files I was polluting the name space and STL should be prefixed with std::crap instead.

Firstly dealing with this is that people often are right - they have a legitimate point. Unfortunately in this case there are other points of greater magnitude.

There is a cost and that of name space collision. The irony is that the above programmer was correct - collision does have to be addressed. But he will not like the answer which is very simple. I have learned to live with name space collisions.

Often I am writing a class and something goes wrong, the first thing I look for is a class with the same name. Its not a nice thing to do, and I really don't like being paranoid when coding, but the benefits of placing stuff in headers are among the above mentioned a faster turn around in writing classes in the same file. So even when I loose out for a particular name space problem, I win in development in one file - it balances in my favor. (e.g. Java people develop the class in its own file, why can't C++ too?)

C++ is egalitarian, if you do get unfavorable collisions just make a library and import through the object file, hiding the header crap in the .cpp file. So he is correct, he just missed 15 years of compiler development.

C is Fast, C++ is Faster in Theory

Faster programs are good for responsive environments(computer games) and number crunching. C produces very fast code because you have to put every frigging thing in yourself. Including memory management.

A profiler is popular which will show where the most amount of time spent in execution. However the order of complexity of the task is the biggest factor. I had code with linear complexity take .5 hour and the same task in seconds with constant complexity, So if you can get constant complexity it doesn't matter how bad your code looks.

C++ has in lining which makes it faster than C (which would do a function call). Indeed this is probably the most important optimization because the code is fully exposed to the compiler for optimizations and it sends it to the point of execution circumventing a possibly costly function call. In lining functions are potentially beneficial in loops.

I said C++ in Theory is faster than C because memory management can be a killer. Having thousands of objects constructed and destructed is no fun. Someone has written a whole book on it(in my book collection). The solution is to be aware of memory constructions(profiler helps) and where possible to pre-allocate memory and constructions - which ideally is of constant complexity.

Adding to "I said C++ in Theory is faster than C" C++ has a habit of making classes with virtual functions extremely attractive which have penalties associated with them. Now C++ does in line virtual functions! But when does this occur, how does this code stack up against non-virtual function code, ... ? I do not know. Note the single biggest reason for virtual functions is a generic container that can be operated on with the same function which for the programmer is the business.

Lastly the compiler often protects the OS from the programmer by doing heaps of memory checking when you just want a bit of memory from new. This sanity helps a lot of programs which otherwise would crash, again a profiler will pick up these errors. Assembly programmers always talk about how fast their code is and they probably have a point. C++ again has a solution and that is that you manage the new operator yourself(generally overload for a particular class).

C is a pain in the arse, but there is always someone who will get pleasure from it.

Arrays and Vectors

Now you may have noticed that I do not like C. However it was brought to my attention that C arrays performed significantly better than STL vector. "STL destroys the cache" as quoted from the same programmer who had a negative view of my inclusion of files in the headers. However this is a godsend. By removing STL from a semi complicated algorithm I got a significant speedup. (I did not do much testing, I looked at the results from the profiler and saw STL dominate, killed STL vector stuff, looked again and other routines dominated).

As a consequence I am no longer using STL vector for performance code. e.g. Computational code. The reason for using C++ as opposed to Java is for control of memory and speed. And while vectors are great because they manage memory it can not be at the price of performance.

The issues are also that I want to write code that is faster than C, plus be OO code. The basic management of memory is still the fastest way to do it and so I recommend allocating with new once before use. And having variables that manage the current size and maximum length.

    T * v;
    unsigned int vsz;
    unsigned int vszmax;

Arrays are the most important data structure. They are accessed generically by an integer and can be used as a stack. Plus work with pointer arithmetic and [ ] . Generally use arrays for your algorithms.

vector<> AMENDMENT

Since you can access a vectors address directly, and the array is contiguous (I believe this was fiercely debated and made true), you can grab a pointer yourself and access the memory directly, avoiding STL's [] operator. So vector<> is back in business.

Temporary Objects Instead of Static Functions

foo().eval(a,b);     foo::eval(a,b);

C++ has static functions, so why then you may wonder why I use foo().eval(a,b) when the same function could have been defined as a static function, removing the dependency of binding the object of the function and generating better code.

Firstly I do not like the different calling convention in an aesthetic sense. Second if the class has a default constructor I see no reason why the compiler should compile and find that there is no reference to the local object. Compilers are lazy. Most times the extra code generated does not matter. If it does then I use the static functions.

Functional Objects

Functional objects are at the core of STL so they are really important, see Functional Objects - a horizontal relationship .

However they have a few drawbacks from a coding perspective. Firstly there is only one signature - the overloaded operator () to draw from. This is good and bad : good then choose wisely how its implemented, bad because their are more things I would like to do.

The other concern important - debugging functional object templates. I have found my compilers error messages harder to understand with operator () than say a function name such as eval(). This is the crunch, I would sooner have my sanity and have a specific named call. You can still write generic code if the other person has the same name too. Since the majority of the time its me - I am not writing libraries but working internally to do a job I may use a named function instead. Since we are dealing with templates this is critical - I want to simplify writing templates as much as possible and this is the way to go.

Name space Collisions

Wrap everything int the .cpp file in its own name space. To ensure that functions/data of the same names do not collide as can happen when linking object files with the same function name. Solve the problem at the language level and make the code more portable. See Compilation: Name space Collisions .

Techniques

Macros

Long held to be the darker side of programming you are told there are things that you must not do. Macros come into play for several reasons. Firstly macros and templates are pre-processing languages and it could be argued that templates are macros with type safety.

The pre-processing language is perhaps known as meta-programming. Anyway its extremely powerful. The concept of doing as much work before you actually do the job is mind blowing. Its organizing the work or calculation differently.

The macro language can be stubborn. My convention is that if it works its ok, but if its configurable its a ripper. Because the macro language did not substitute H3 in nH3 I fell back on the C++ language. By wrapping in { } the variable nH3 does not collide with other variables of the same name which are generated through repeatedly calling the macro. Its amazing that C++ allows you to do this when you need it.

#define TET3SIDE(H3,P0,P1,P2) \
{ \
  point3<T> nH3(tetrahedron<T>::H3.pn*-1.0); \
  nH3.normalize(); \
  displaywindingside(c,nH3,tetrahedron<T>::P0,tetrahedron<T>::P1,tetrahedron<T>::P2); \
}

Multi-line Macros

The #define is restricted to one line. So if you want to include other # directives this is not possible.

To get around this you could write the multi-line statement yourself every time you do that operation - or write the macro differently.

Here is the code I would like to write.

#definemultiline gobjlog_draw(variable)
#ifdef GOBJDEBUG01_H
#define gobjlog_draw(variable) { gobjlog log; variable.draw(); }
#else
#define gobjlog_draw(variable) variable.draw();
#endif
#enddefinemultiline

This is the code I write to get the same effect.

#ifdef GOBJDEBUG01_H
#define gobjlog_log gobjlog log;
#else
#define gobjlog_log
#endif

#define gobjlog_draw(variable) { gobjlog_log variable.draw(); }

The two pieces of code are different - scope brackets { } are included with the workaround which is language dependent - then I have to think how C++ behaves here which is an extra complexity that I would care to do without. Further two macro functions are defined rather than one. I really object to the brackets more than the namespace collision.

So multi-line macro's are easy to write. Provides a pre-processing language - can get to the code before the C++ compiler can and hence build other programming languages - C/C++ really is mutable!

Templates

I use templates in primitive ways. For example there is a direction to use techniques and new language features to parse the template arguments. While this appeals to some it is just more machinery - and the same effect can come by other more primitive means.

So if I have this template argument list<double> and I need to extract double then I use two separate template parameters to pass the information in (< list<double>, double >).

Another technique is to use a typedef to extract the double type, see [2]. I do not have a problem with this template technique because I use it myself. For example a template argument representing a point I assume to have .x and .y access members. Here the typedef is for a type and not a member. typedef double Type; I openly encourage template use in this way. I even prefer a named function to overloading the operator () because it is easier to identify an error in the template error messages with a name. The named functions while as generic can have any number in one class whereas there is only one operator () in a class.

How templates are used is also a philosophical issue. If something is undefined the compiler only needs look at it when it is defined. Therefore it is the programmers responsibility to catch or identify errors at compile time. If you can not track down your error then perhaps your design of the template class was not good. Perhaps you are using templates in a too complicated fashion when an easier one will do. I do not like a lot of the templated code I see because I believe in simple code. The cost in this case is larger template parameter lists. The code produced should however work on any C++ compiler that supports basic templates. I only use templates to substitute something in. I do not want the language to interpret what goes in any more than necessary.

Now there will be a situation where someone has a must have template feature. In that case use it. If the template argument list gets too long then the class can always be broken down into smaller components. The majority of the time we are limited not by what we do but by what other programmers do. So unfortunately you have to deal with complicated template code anyway.

Note that if compilers over night changed and compiled template code ideally and had tools that could handle it I might change my opinion. Just using templates in this primitive way caused problems for compiler tools such as gdb which on my version can not step through templated code in certain situations - which I found out when I really needed it.

Circular References

Traditionally programmers regard circular references as bad. Logicians and mathematicians have banned them. And of course they are discouraged from C++ because they have compiler problems. The compiler essentially needs to know the size of the object and if it can not determine the size then it will not compile.

Even with separate header and definition files my compiler still will not compile two circularly referenced objects. But since Java can do it I do not see why C++ programmers can not.

Since a pointers size can be determined from the class declaration then have both classes refer to each other with pointers. This code is totally generic and a pain because you have to manage the memory but it should be able to be compiled on every C++ compiler.

// In file B.h
class A;
class B { ...
  A* pa; ... }

// In file A.h
class B;
class A { ...
  B* pb; ... }

The Underscore Character _

I got caught out here where I was using the convention of an underscore before a variable name. This is fine if the following character is lower case, but given an uppercase variable the compiler owns the space and a collision occurred.

Here is my ideal thinking.

C++ religiously defines this character prefixing a name to be owned by the compiler. While this in one sense good for the compiler vendor it does nothing for the programmer - well it is a negative because it takes away a very useful character.

Here is a practical solution. Append the underscore to the end and not the start of the variable name.

By convention I use underscores in variable arguments. This is so that the variable can be easily identified with the class member of the same name and I do not use underscores if there is no class member with the same name.

class hat
{
public:
  double x
  hat(double const x_)
    { x = x_; }
};

Alternatives to the underscore are ugly. For example if you prefix it with a letter then the human reads the letter as part of the variable name. The underscore is naturally read as an invisible character - there are no words that use it as a letter. This is its advantage. In my opinion any other character will look weird.

This is a known convention and is used at workplaces. (especially before the newer C++ rules came in).

I was corrected in a Cygwin forum, and given a technique to test the situation. Compilers have an option for displaying the pre-processed source code. In g++ it is -E.
So g++ -E main.cpp > /tmp/s01.txt outputs the code after pre processing. Upon looking at the area where the compiler was breaking (which was suggested I do so in the forum) I could see the macro substitution.

On 16 April 2007 15:14, Chelton Evans wrote:

> Pre fixing the underscore character is a technique that was around
> before the language evolved.

> The compilers that I had used I had not encountered this before.

  :-)  Welcome to the post K'n'R world.  Things have changed a lot since
pre-1989; there's nothing else for it really, old code just has to be tidied
up.

> However after this discussion I will add the underscore character to
> the end of a variable instead of the start

  This is a well-used and fairly standard technique, particularly in
function-like macros where you want to avoid the risk of clashing with a
variable in the enclosed function.

> I went and checked the pre-processed code and a macro substitution had
> occurred. 

  Heh, knew it.  Glad it's all cleared up now.

    cheers,
      DaveK

Exception handling

I do not use exception handling code for several.

Just because you see no exception handling code in my source does not mean that I do not know how to write exception handling code. Not using exception handling code is a design choice.

I was asked what happens when the code breaks. The answer is simply that it is made into a bug report - for me this is a TODO in the projects page and at some point corrected. For a commercial application the bug would be fixed for the next product release.

For C++ code is often cut and pasted. At this point the code is not fixed in design. I am writing algorithms (often experimental) and I want the bare minimum in the interfaces. Since exception handling impacts on both performance and the code interface by not having it I am doing myself a favor.

Performance is also an issue and some libraries can be compiled with and without exception handling code so not having exceptions is done in practise.

The real reason for using an exception is and will always be the situation where one object passes control back to the caller such that the two parties are separate. For example a maths library generates a divide by zero error. The library writer knows there is an error but has no context. The client has the context but can not get into or see inside the library. Exception handling solves this dilemma by having the library writer write the exception, for which the client is responsible for dealing with it.

References

  1. D.Vandevoorde and N.M.Josuttis (2003). C++ Templates The Complete Guide. ISBN 0-201-73484-2. Pages 3-4.
  2. D.Vandevoorde and N.M.Josuttis (2003). C++ Templates The Complete Guide. ISBN 0-201-73484-2. Pages 264-268.

Issues