C++ Programming Style

Ö

Öö Tiib

Are you serious?  Even if you use that style yourself, surely you know
almost noone else does?

With simple things like that it is pointless to split the line
usually. However if line gets long then i split it. If it is
calculation line then operator first and with the parameters i split
comma first. Reason is that for me second of two feels easier to read,
since first of two lose the operator + to peripheria:

Calculationresult sum = something +
somethingElse;

Calculationresult sum = something
+ somethingelse;

That however is personal taste. Most important is to do it uniformly
and follow *same* style in all code-base of product.
Let me put it this way: there are too many weird things in there; if
the OP starts following it he'll write code which looks weird. I think
most people here agree that many of the things the guide calls "common
practice" aren't common.

Creating some canonical style of writing C++ in general is impossible
because everybody have their favorite style. On any rule there are 1/3
who say it is natural and 1/3 saying it is ugly nonsense and 1/3
saying that they don't care. Therefore writing such style guide for
bigger C++ projects is a must. If everybody will write code in their
own favorite style then the code base will look outright comical ... i
have seen it.

The links that OP posted are good material to use when discussing
style of project's codebase with team. If majority disagrees with some
rule then set direct opposite as rule. Leaving it loose is usually
most damaging.
 
J

James Kanze

It can not be recommended. A short glimpse reveals several errors -
the first one being, that constant identifiers should be all uppercase
(eg. int MONTHS_PR_YEAR = 12). This is plain wrong - did the author
come from Java?

Not wrong, just very unexpected (or unusual) in a modern C++
guidelines. As for why, one explination could be that the
guidelines were originally written a long time ago, and this
point hasn't been updated. Using all caps for constants was
usual in C++ coding guidelines until the late 1990's.
 
J

James Kanze

I don't think you can call it "wrong". Their rationale is wrong, though:
"Common practice in the C++ development community."

Which makes me think that it's simply showing the age of the
guidelines. Until the late 1990's, and even later, it was the
usual practice.
Personally I do it that way too, but I'm aware that most people on
c.l.c++ don't (and you can end up in a flamewar by arguing for it.)

Two "arguments" are generally given against it:

-- You need something do distinguish macros (which don't obey
scope, and can modify syntax), preferrably something which
really stands out, and if you use all caps for constants,
it's no longer available for macros. People arguing this
point of view generally also point out that the tradition
comes from C---you don't find it in other languages---and in
C, such constants are macros, so it is justified.

-- "One man's constant is another man's variable":). I
started arguing against all caps for constants when on
several occasions, the constants written in all caps ended
up being read from a configuration file.

The C++ community in general seems to have adopted the first
argument; there seems to be a large consensus about it. (I
think. To tell the truth, I've never verified.) The second
argument is, quite frankly, my own, and I've not been able to
convince many people about it, so it's not a concensus.

Anyway, the important concensus isn't the C++ community in
general, but the people actually working on the code. If most
of them do come from the Java world, or are old enough to have
experienced (and maybe liked) the earlier tradition, there's no
harm in adopting the convention of all caps, provided every one
is aware of the issues I mentioned, and provided you're aware
that the current overall consensus is different.
 
J

James Kanze

[...]
Nitpicks: I prefer NULL over 0 for pointers (it sticks out like a sore
thumb);

I'll second that, but I think it partially depends on your
coding style; in many ways, neither is an acceptable solution
(but until C++0x becomes wide spread, there aren't any other
alternatives). If you make heavy use of templates or overloaded
functions, then you have to consider the fact that NULL will not
give the same results as a pointer would, despite appearances.
(Of course, if you're using g++, this argument doesn't apply,
since if NULL isn't converted to a pointer type, g++ warns.)
I don't mind shortening command to cmd or initialize to init;

Most projects I've worked on have had a short list of accepted
abbreviations. Generally with the rule that if a word is in
that list, the abbreviation must be used. (In an ideal word, I
could dictate code over the phone, and everyone working on the
project would spell it exactly the same way.)
 
J

James Kanze

On 3/30/2011 12:50 AM, crea wrote:
There are many common C++ practices in the "community". Camel
case is far from the most popular. In fact, using it can get
you into trouble if you're coding on windows
systems.(1,2,6,etc...)

CamelCase is one popular convention. Certainly not the only
one. Practically speaking (rather than esthetically), it's as
good as any of the alternatives. In some environments (e.g.
telecoms), it's almost universal; in others, other conventions
may predominate. Choose one, and stick with it, but which one
doesn't really matter.
The all-caps constants thing has been beat to death already.
Requiring single letter template parameter names is just plain fucking
stupid. REALLY fucking stupid. (8)

Single letter names for anything except loop control variables
should be banned, not encouraged.
Requiring variables to be named exactly the same as their type is also
really fucking dumb. (12)

It's impossible to meet. What happens if you have two or more
variables with the same type? The general rule is that the
names for variables should be a qualified noun, those for types
an unqualified noun; if followed rigorously (it rarely is), then
a variable will never have the same name as its type.
Getters and setters are smelly. That this group has an actual naming
convention for them is dubious. Requiring get/set as prefixes is just
silly, especially since C++ does overloading.(17)

It's not a convention that I particularly like, but it does seem
one of several which are widespread.
Using i,j,k,etc.. for iterator value names is a questionable practice.
Many people do in fact do it, because it's just easy and fairly well
recognized, but its a lazy practice and should certainly not be
recommended/required by a team style guide. Quite frankly, if you find
yourself using more than just 'i' then you need REAL names for your
iteration variables. (25)

For iterator values, I don't know, but in numeric processing,
when indexing into matrices, i and j are definitely the most
expected names.
I totally disagree with the examples in #39. COMMA FIRST!
function( param1
, param2
, param3 )
If you're going to split, do it. Don't mix and match; it's much harder
to read.

I totally agree with both of these points, but I think we're in
a minority here. I haven't seen much code which puts the comma
on the line with the following text. And if you indent
consistently, it's not too bad otherwise:

function( param1,
param2,
param3 )
 
J

James Kanze

On 3/30/2011 3:18 PM, Keith H Duggar wrote:

On 31 Mrz., Drew Lawson wrote:
At one point in my college freshman year, I tried to learn Pascal
without buying the text book. I was guided mostly by compiler error
messages.
Error: line 17, missing semicolon
I ended up spending 6 months thinking that Pascal code was supposed
to have lines starting with semicolons.
That's what the comma-first stuff reminds me of.
LOL, that's a good one (a hearty laugh is a good start into the day).
Now that I've come to think about it, I can't come up with a reason
why every statement should be terminated by a semi-colon other than it
makes things easier for the compiler.

You mean easier for the reader. Whether the semi-colon is a
statement separator or a statement terminator makes no real
difference when writing a parser. Figuring out where you need
semi-colons, and where they're forbidden, when they're
separators, is a real problem for the person writing the code.
Up to this day I have only ever
used one language that doesn't require an explicit "statement
terminator", which is Visual Basic (it uses newlines as terminators,
so it's not a terminator-free language in the purest sense).

The Pascal family used semi-colons as statement separators, not
terminators. In Pascal, in something like:
IF expression THEN something; ELSE somethingElse;
the first semicolon is illegal, since it terminates the IF
statement (and leaves the ELSE dangling). Later languages in
the Pascal family adopted a policy of designing the grammar so
that every context which accepted a statement accepted a list of
statements: in Modula-2, that IF would be:
IF expression THEN something; ELSE somethingElse; ENDIF
The semicolons aren't necessary, but they become legal, since a
sequence of statements are legal; "something;" is parsed as two
statements, "something" and an empty statement.
 
J

James Kanze

Pascal code is best written by teams of two: one to write the code and
one to write the semicolons.

Or to remove them: the semi-colon in "IF expr THEN something;
ELSE whatever" is illegal in Pascal.
 
J

James Kanze

[...]
You missed a few spectacular ones.
#34, "... Source files can have the extension .c++ (recommended), .C,
.cc or .cpp". I have never, ever seen a source file named foo.c++.
My editor recognizes it, but that's about it.

I wouldn't recommend .C either. But then, I'm working on
Windows platforms at present.
#36, where they seem to forbid inline functions and whatnot because
"the header files should declare an interface, the source file should
implement it."

It's not a bad rule, if applied with constraint. The problem is
that it can't be applied to templates.
#53, "Implicit test for 0 should not be used other than for boolean
variables and pointers." I don't argue with that, but they give the
rationale "It is not necessarily defined by the C++ standard that ints
and floats 0 are implemented as binary 0." Surely that's irrelevant
here, just like it is for the null pointer?

The real question is why they allow pointers.

And for better or worse, the implicit test should also be used
on streams (istream and ostream). IMHO, it's a horrible
convention, but it is so ubiquous that doing anything else
raises questions.
#71, "Basic indentation should be 2." -- I'm sure a small minority
prefers that, but I've worked with such code for a few years and I can
tell it's /stupid/. I have been unable to find anyone at my workplace
who argues for anything less than 4 (the people being responsible for
2 having left many years ago).

I used to prefer 3. I've given up on that; as you say, four now
seems universal.
#92, use only // for comments, so you can reserve /* */ for commenting
out huge blocks of code. This is surely Java bias again -- in C++ you
use #if 0 for such things (or at least I do).

The easiest way to comment out a block of code, and being sure
that the casual reader clearly sees that it is commented out, is
to prefix all of the lines with "// ". To recover it, delete
the first four characters in the lines. With any reasonable
editor, both operations are trivially simple. (With my editor,
the first is ":s:^:// :" and the second ":s/....//".)
 
J

James Kanze

[...]
You missed a few spectacular ones.
#34, "... Source files can have the extension .c++ (recommended), .C,
.cc or .cpp". I have never, ever seen a source file named foo.c++.
My editor recognizes it, but that's about it.
These aren't that weird if you're working on Unix, especially with older
code. The .cpp extension is actually the new one as I understand,
standardized for little or no more reason than that VS does it.

I've never seen .c++. Stroustrup, in the first version of _The
C++ Programming Language_, uses .c, but all of the oldest code
I've seen used .C. Which caused problems under MS-DOS; I
suspect that it was Walter Bright (and Zortech C++) which
introduced .cpp---the Zortech compiler accepted both .cpp and
..cxx (and maybe .cc, I forget). That was my first C++ compiler
(around 1989), and my first C++ used .cpp. Professionally
(since around 1992), I've used almost exclusively .cc (which
they don't mention); I can't figure this out, because I've
almost never seen it outside of the places I've worked.

With regards to VS: Microsoft was about the last major provider
of C to adopt C++; they just adopted the conventions established
by Zortech and Borland under MS-DOS (where .C didn't work).

[...]
Maybe the people you work with are the stupid ones (see how that
works?). Using 2 spaces is almost certainly the predominant view out
there. Most published standards use it. We use it here. AFAICT most
open source code uses it... There's really no reason for anything more.
2 is enough to make the indentation quite clear; nothing is gained with 4.

Again, I've never seen anything but 4. Dating from the days of
C. I find 2 too little; it doesn't make the indentation clear
(but if the code is complicated enough for that to matter,
you've got more important problems), but 3's nice. Still, I've
given up fighting it. Four seems to be universal.
I do realize there's a wide amount of new developers who never outgrew
the VS defaults, but to call an opinion that doesn't actually effect
readability at all "stupid" is pretty fucking stupid.

Don't blame everything on VS. Four has been universal since the
early days of C, before C++, much less VS, even existed.
And if they commonly switch from Java to C++ and back, this makes some
amount of sense.

Not really. /* */ don't nest, and most JavaDoc comments I've
seen use /** ... */, so you have to be careful what you comment
out. Just editing in "// " at the start of each line works
well in both languages.
 
J

James Kanze

Borland used .cpp long before Microsoft had a C++ compiler.

And Zortech used .cpp long before Borland had a C++ compiler:).
The "standard" was .C, but that doesn't work too well on a
system where filenames are not case sensitive.
 
J

James Kanze

Rui Maciel wrote:
In
numeric_type var;
...
assert( !var );
you're testing that the conversion into bool results in false. How do
you know that this isn't what "you" intended to test? For all types
where a conversion to bool is defined in a way that makes sense for this
assertion, it is IMO ok to use it.

Readability is the issue. C++ defines a lot of implicit
conversions, including almost every scalar type to bool. But if
you know what the conversion is that you want, why do you want
to hide it from the reader. "var != 0" is far clearer, since it
says exactly what you are testing for.
 
J

James Kanze

On 03/04/2011 14:34, James Kanze wrote:
Specifying an indentation width is retarded: just use tabs and
configure your source editor to display them at any width you
see fit.

And make it impossible to view the code correctly with most of
the tools a professional programmer regularly uses.
 
J

James Kanze

crea said:
Noah Roberts wrote:
[snip]
I totally disagree with the examples in #39. COMMA FIRST!
function( param1
, param2
, param3 )
If you're going to split, do it. Don't mix and match; it's much harder
to read.

Personally, I use the following style: blanks between function name
and parenthesis, comma attached to the word after which it comes.
function (param1,
param2,
param3);
That is what the German Duden (something similar to Webster's
dictionary, I guess) defines as typographic convention for machine-
written documents.

The Duden goes well beyond Wbsters:). The problem is that
local typographical conventions don't map well to code:
punctuation in code often has significantly more meaning than it
would in normal text. (There's also a problem that local
typographical conventions are just that: local. I learned to
program in France, and for many years, I introduced a space in
front of semi-colons, because that's what the French
typographical conventions require.)

In the case of parentheses: parentheses have three different
uses in C++: they can be part of the syntax (while or if, for
example), they can signify function invocation, or they can
simply group. When I have the choice (i.e. I don't have to
conform to an existing coding guideline, or existing code), I'll
distinguish the three meanings:

if ( expr ) ...
function( expr... )
a * (b + c)

But I try to conform to the local practices where I'm working
(which do differ according to the country: the French use a lot
more white space than the Germans, for example).
Since this style is used for virtually any English
and German prose, I think that computer programs should adopt the same
style. After all, people who read a lot are quite adjusted to this
style, and would find a different style ugly.

See above. In normal English (or German or French) prose,
parentheses have only one meaning. In C++, they play three
distinct roles.

[...]
However, I disagree with the other style that is suggested in #39: I
prefer the style where the operator is moved to the next line:
totalSum = a + b + c
+ d + e;
or even more detailed:
totalSum = (a + b + c)
* (f + g)
+ h + i;

Agreed. When scanning code, you'll only look at the first token
or two in each line. Any acceptable guideline should ensure
that this is sufficient to make clear what the line does:
control flow, state modification *or* just a continuation of the
previous line. Of course, indentation can help here as well.
 
J

James Kanze

[...]
However, I like,
my_class::my_class(p1, p2, p3, p4)
: m1(p1)
, m2(p2)
, m3(p3)
, m4(p4)
{}

Except that initializers are not a top level construct, and
should be indented.

Add the indentation, and this is very close to what I do in my
own code. Indentation can add a lot of useful information,
however, and something like:

my_class::my_class(p1, p2, p3, p4)
: m1(p1),
m2(p2),
m3(p3),
m4(p4)
{
}

is also quite readable.
 
J

James Kanze

Far clearer? You wouldn't write "var != false" if "var" was a bool.

No. There's no implicit conversion involved if var is a bool.
To be honest though I don't recall using implicit conversion
to bool for numeric types but I do use the conversion for
pointer types.

Which is, from what I gather, the recommmendation in the
document initially cited.

Personally, I've thirty years experience with C and C++, and the
implicit conversions to bool still confuse me when I see code
using them.
 
J

James Kanze

On 03/04/2011 15:37, James Kanze wrote:
One word: bullshit. Tabs FTW. The only problem with tabs is if your
project includes source code written by others who are not following the
same convention in which case I would, if allowable, tabify such code.

Or if any of the developers in the project want to use some tool
that understands tabs differently. Like diff or grep. Or any
of the merge tools I've seen, or just about any tool. About the
only time using tab's is a viable option is if you never view
the source code outside of your one prefered editor, which has
tabs configured to the way you want. Which means in practice,
in real projects, never.
 
J

James Kanze

With my editor, the first is cmd-/ and the second is cmd-/. Works for
all supported languages, too: C, C++, LaTeX, HTML, ...

Yes. I could certainly configure my editor with such language
dependent commands, but I've never bothered. I guess I learned
all of this too long ago, and now have some very complicated
commands programmed into my fingers, so I often don't bother
with "reprogramming" the editor. Or even looking for packages
that would do it for me. (But I think what your describing
comes out of the box with emacs.)
 
Y

Yannick Tremblay

In any less than small project, you will end up with some code that is
using a different indentation style somewhere. Code that exclusively
use tabs can be readable with properly setup viewer. Code that
exclusively uses space is viewable with any viewer. The worse however
is code that uses a mix of tabs and spaces, this become only viewable
is your viewer is configured exactly the same way as the editor of the
last author.
Again with the bullshit. If your tools cannot handle tabs then your
tools suck but I find it hard to believe that handling tabs is a problem
for the majority of tools (I have never encountered any problems).

Could you enlight us on what tool you use? It seems to me that you
are only using a very small number of tools. Typically, I view code
in several times more different viewers than the number of tools I use
to edit or modify code.

Certainly, to setup my code modification tools to use spaces only
require only a small fraction of the effort that would be required to
setup all of the code viewing tools that I use. First of all the
first class are a lot less numerous and generally, the indentation
settings are easy to find and designed for this purpose.

The Good:

- Visual Studio or other IDE: OK tabs can be configured to your liking.
- Decent code editior: OK tabs can be configured to your liking.

The Bad:

- Graphical debuggers: Tabs might be configurable but default are
rarely correct adding pain to the setup.
- Graphical diff tools: Tabs might be configurable but that's yet one
more thing to configure
- Source control tool: again, may or may not be friendly to configure
for previewers, diff/merge, annotated viewer, etc.
- GUI profiler
- GUI analysing tool

The Ugly:

- Command line: cat, more, less: albeit the tabs on the terminal may
be configurable, they are rarely set for code purpose
- Email and IM: as above. I'll often copy-paste code snippet to
colleagues by email or IM.
- Word Processors: tabs are set for text purpose so should not be
messed up to code settings but most devs will end up having to put
some code in a word processor.
- Usenet: many readers use text-only client and of course this
newsgroup has a lot of code posted.
- Web-based bbs: typically, it is impossible for individuals to set
tabs in these.
- Command line profilers and analysing tools


Yannick
 
Y

Yannick Tremblay

Any hint about what tools you use? You seem to be pretty limited in
what you use?

Do you exclusively develop on Visual Studio in a Windows environment
and exclusively work on GUI applications?
Having to configure a tool does not make that tool "bad".

That was a reference to a movie that most probably predate you. It
sounded better than "The good, the nuisance, the major pain in the
back side" :)

Anyway, having to configure a tool is worse than not having to
configure a tool. In a perfect world, I would never have to configure
anything because they would do exactly what I want all of the time.

I've already mentioned it above but I'll repeat very very explicitly:

Number of tools used for editing or modifying code = E
Number of tools used for viewing code = V

E is significantly smaller than V (typically a small fraction)

- You will almost always have to configure and adjust your editing
tools. They are the tools that you probably spend the most time
using and you probably need to get them set exactly as you need
them.

- You only need to modify the viewing tools if the code (produced by
the editing tools) is not displayed properly in your additional
viewing tools.

So essentially, you can either:

- Configure E tools in a certain way to makes the code displayed in V
viewing tools not readable and as a consequence have to configure an
additional V tools. Total configuration needed E+V

- Configure E tools in a certain way to makes the code almost
universally viewable in all most all viewing tools. Total
configuration needed = E.

E+V is definitely larger than E
(especially given that V is already much larger than E)

I am lazy, I choose to do the minimal amount of configuration and
concentrate on configuring E tools correctly so that I don't need to
worry about the additional V tools..
How can the choice of tabs or spaces for indentation whitespace possibly
affect the operation of a profiler?

Euh? Are you serious? Many GUI profilers can display source code
with things like number of time a function is called or amount of time
/ amount of CPU time used by a call embedded in the source in a useful
manner. Actually, I fail to see the point of a GUI profiler if it
can't display code ?!?
Same again.

Same again.
Fine if you use the command line to examine source code; I don't as I
don't live in the past.

:)
You don't live in the future either. Try working on embedded
development without being able to use a command line. Did you think
embedded development was the past?
I don't have any problems with tabs and e-mail; maybe your choice if
client sucks.


Again I don't have any problems with tabs and word processors; one word:
rulers.

Yes, you can adjust the tabs width in an email client or a word
processor by using the rulers so that code display correctly.
But that's the whole point, you are giving yourself additional work by
using tabs. If you'd use spaces, you would not need to adjust the
rulers, they can be left in their natural space for text and formatted
and indented code appears as it should.

Again, I am lazy. I prefer doing no work than having to do work.
Maybe you are not.
Here is some tabbed code sent from my usenet client:

class auto_join_entry
{
public:
// types
public:
// construction

Seems to work no?

And is displayed in a text client as 8 spaces which is the default
tabs width for text terminal but not very suitable for code
indentation.
The <pre> HTML tag seems to respect tabs in most browsers.

So the reader will again typically see an indent of 8 spaces which
makes anything that is more than trivial rapidly move to the far
right.
Again with the command line..

I use the tools that a productive. The command line is often the most
productive tool. Sometimes it is the only tool available.

Yannick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top