66

What are your favorite C++ coding style idioms? I'm asking about style or coding typography such as where you put curly braces, are there spaces after keywords, the size of indents, etc. This is opposed to best-practices or requirements such as always deleting arrays with delete[].

Here is an example of one of my favorites: In C++ Class initializers, we put the separators at the front of the line, rather than the back. This makes it easier to keep this up to date. It also means that source code control diffs between versions are cleaner.

TextFileProcessor::
TextFileProcessor( class ConstStringFinder& theConstStringFinder ) 

    : TextFileProcessor_Base( theConstStringFinder )

    , m_ThreadHandle  ( NULL )
    , m_startNLSearch (    0 )
    , m_endNLSearch   (    0 )
    , m_LineEndGetIdx (    0 )
    , m_LineEndPutIdx (    0 )
    , m_LineEnds      ( new const void*[ sc_LineEndSize ] )
{
    ;
}
Martin York
  • 234,851
  • 74
  • 306
  • 532
Foredecker
  • 7,281
  • 4
  • 27
  • 30

24 Answers24

69

RAII: Resource Acquisition Is Initialization

RAII may be the most important idiom. It is the idea that resources should be mapped to objects, so that their lifetimes are managed automatically according to the scope in which those objects are declared.

For example, if a file handle was declared on the stack, it should be implicitly closed once we return from the function (or loop, or whichever scope it was declared inside). If a dynamic memory allocation was allocated as a member of a class, it should be implicitly freed when that class instance is destroyed. And so on. Every kind of resource—memory allocations, file handles, database connections, sockets, and any other kind of resource that has to be acquired and released—should be wrapped inside such a RAII class, whose lifetime is determined by the scope in which it was declared.

One major advantage of this is that C++ guarantees that destructors are called when an object goes out of scope, regardless of how control is leaving that scope. Even if an exception is thrown, all local objects will go out of scope, and so their associated resources will get cleaned up.

void foo() {
  std::fstream file("bar.txt"); // open a file "bar.txt"
  if (rand() % 2) {
    // if this exception is thrown, we leave the function, and so
    // file's destructor is called, which closes the file handle.
    throw std::exception();
  }
  // if the exception is not called, we leave the function normally, and so
  // again, file's destructor is called, which closes the file handle.
}

Regardless of how we leave the function, and of what happens after the file is opened, we don't need to explicitly close the file, or handle exceptions (e.g. try-finally) within that function. Instead, the file gets cleaned up because it is tied to a local object that gets destroyed when it goes out of scope.

RAII is also less-commonly known as SBRM (Scope-Bound Resource Management).

See also:

  • ScopeGuard allows code to "automatically invoke an 'undo' operation .. in the event that an exception is thrown."
jalf
  • 229,000
  • 47
  • 328
  • 537
61

When creating enumerations, put them in a namespace so that you can access them with a meaningful name:

namespace EntityType {
    enum Enum {
        Ground = 0,
        Human,
        Aerial,
        Total
    };
}

void foo(EntityType::Enum entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}

EDIT: However, this technique has become obsolete in C++11. Scoped enumeration (declared with enum class or enum struct) should be used instead: it is more type-safe, concise, and flexible. With old-style enumerations the values are placed in the outer scope. With new-style enumeration they are placed within the scope of the enum class name.
Previous example rewritten using scoped enumeration (also known as strongly typed enumeration):

enum class EntityType {
    Ground = 0,
    Human,
    Aerial,
    Total
};

void foo(EntityType entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}

There are other significant benefits from using scoped enumerations: absence of implicit cast, possible forward declaration, and ability to use custom underlying type (not the default int).

ostappus
  • 173
  • 1
  • 10
kshahar
  • 9,617
  • 9
  • 45
  • 66
  • 1
    no semicolon after namespaces required though. is that a typo? – Johannes Schaub - litb Nov 10 '08 at 18:55
  • 30
    How can an answer be "accepted" for such a question ? No offsense to kshahar, it's a good technique, but "accepting" an answer automatically brings it to the top and doesn't let a more democratic evaluation process to take place, which is a shame for a "what's your favorite..." question – Eli Bendersky Nov 14 '08 at 20:39
  • 2
    I agree with this, except that I generally do it as classes. (This is because I have some code generation that lets me do enum-to-string and string-to-enum conversion automatically.) – Austin Ziegler Nov 18 '08 at 19:16
  • 3
    now it's time of strong typed enum :) – Mr.Anubis Oct 16 '11 at 10:54
40

Copy-swap

The copy-swap idiom provides exception-safe copying. It requires that a correct copy ctor and swap are implemented.

struct String {
  String(String const& other);

  String& operator=(String copy) { // passed by value
    copy.swap(*this); // nothrow swap
    return *this; // old resources now in copy, released in its dtor
  }

  void swap(String& other) throw() {
    using std::swap; // enable ADL, defaulting to std::swap
    swap(data_members, other.data_members);
  }

private:
  Various data_members;
};
void swap(String& a, String& b) { // provide non-member for ADL
  a.swap(b);
}

You can also implement the swap method with ADL (Argument Dependent Lookup) directly.

This idiom is important because it handles self-assignment[1], makes the strong exception guarantee[2], and is often very easy to write.


[1] Even though self-assignment isn't handled as efficiently as possible, it's supposed to be rare, so if it never happens, this is actually faster.

[2] If any exception is thrown, the state of the object (*this) is not modified.

Community
  • 1
  • 1
RC.
  • 25,495
  • 8
  • 69
  • 90
  • Some text explaining why/how/when this is useful, perhaps? – jalf Jan 09 '10 at 18:49
  • 5
    Is there a reason for "using std::swap;" instead of just "std::swap(data_members, other.data_members);"? – leetNightshade Jan 11 '12 at 15:18
  • 3
    leetNightshade: This way, if a class member uses the copy-and-swap idiom too, argument-dependent lookup should call the better-optimized swap function. std::swap will generally call a copy constructor (move constructor in C++11+) and two assignment operators, and for copy-and-swap, each assignment operator will call the class-specific swap function anyway. Therefore, using std::swap would cost twice as much, PLUS the cost of a move or copy constructor. That's not to say copy-and-swap makes std::swap super-slow; the specialized version is just better. – Mike S Aug 21 '14 at 05:22
  • 1
    Why do you need the non-member version of swap? – schanq Feb 19 '15 at 00:30
  • @schanq read the comment directly above yours--so that way other classes in your codebase using the aforementioned idiom will have a 'better-optimized swap function' for your type (here `String`) accessible to use instead of `std::swap` thanks to the power of argument-dependent lookup when resolving `swap` – obataku Aug 05 '16 at 20:42
  • 1
    `throw()` is deprecated since C++11, and since C++17 it is the same as `noexcept` (http://en.cppreference.com/w/cpp/language/except_spec) – Ale Jun 04 '18 at 20:17
34

CRTP: Curiously Recurring Template Pattern

CRTP happens when you pass a class as a template parameter to its base class:

template<class Derived>
struct BaseCRTP {};

struct Example : BaseCRTP<Example> {};

Within the base class, it can get ahold of the derived instance, complete with the derived type, simply by casting (either static_cast or dynamic_cast work):

template<class Derived>
struct BaseCRTP {
  void call_foo() {
    Derived& self = *static_cast<Derived*>(this);
    self.foo();
  }
};

struct Example : BaseCRTP<Example> {
  void foo() { cout << "foo()\n"; }
};

In effect, call_foo has been injected into the derived class with full access to the derived class's members.

Feel free to edit and add specific examples of use, possibly to other SO posts.

Community
  • 1
  • 1
  • 5
    If ever an idiom had a bad name (and C++ has some lulus) then this has got to be it. I think you should describe at least one of the curious uses for this answer to be useful. –  Jan 09 '10 at 18:38
  • 4
    It's called the Curious_ly_ recurring template pattern. That's an adverb: the recurrence is curious, not the pattern :-) – Roger Lipscombe Jan 09 '10 at 18:41
  • @Roger Pate: Why post an answer and vote to close? – jason Jan 09 '10 at 19:45
  • I voted to close before the question changed drastically. –  Jan 09 '10 at 19:47
  • How can this be your favorite? I have used it, but each time I step over it I have to start thinking from the beginning. Unnecessary complicated IMHO. – Nils Jun 06 '14 at 12:22
  • 2
    @Nils Performance! `self.foo` is statically dispatched to `Example`, whereas a `virtual` method call would by dynamically dispatched, which **is** slower if you're pedantic about micro optimizations! – mucaho Mar 28 '16 at 22:28
28

pImpl: Pointer-to-Implementation

The pImpl idiom is a very useful way to decouple the interface of a class from its implementation.

Normally, a class definition must contain member variables as well as methods, which may expose too much information. For example, a member variable may be of a type defined in a header that we don't wish to include everywhere.

The windows.h header is a prime example here. We may wish to wrap a HANDLE or another Win32 type inside a class, but we can't put a HANDLE in the class definition without having to include windows.h everywhere the class is used.

The solution then is to create a Private IMPLementation or Pointer-to-IMPLementation of the class, and let the public implementation store only a pointer to the private one, and forward all member methods.

For example:

class private_foo; // a forward declaration a pointer may be used

// foo.h
class foo {
public:
  foo();
  ~foo();
  void bar();
private:
  private_foo* pImpl;
};

// foo.cpp
#include whichever header defines the types T and U

// define the private implementation class
class private_foo {
public:
  void bar() { /*...*/ }

private:
  T member1;
  U member2;
};

// fill in the public interface function definitions:
foo::foo() : pImpl(new private_foo()) {}
foo::~foo() { delete pImpl; }
void foo::bar() { pImpl->bar(); }

The implementation of foo is now decoupled from its public interface, so that

  • it can use members and types from other headers without requiring these dependencies to be present when the class is used, and
  • the implementation can be modified without forcing a recompile of the code that uses the class.

Users of the class simply include the header, which contains nothing specific about the implementation of the class. All implementation details are contained inside foo.cpp.

jalf
  • 229,000
  • 47
  • 328
  • 537
22

I like lining up code/initializations in 'columns'... Proves very useful when editing with a 'column' mode capable editor and also seems to be a lot easier for me to read...

int myVar        = 1;    // comment 1
int myLongerVar  = 200;  // comment 2

MyStruct arrayOfMyStruct[] = 
{   
    // Name,                 timeout,   valid
    {"A string",             1000,      true    },   // Comment 1
    {"Another string",       2000,      false   },   // Comment 2 
    {"Yet another string",   11111000,  false   },   // Comment 3
    {NULL,                   5,         true    },   // Comment 4
};

In contrast, the same code not indented and formatted as above would appear... (A little harder to read to my eyes)

int myVar = 1; // comment 1
int myLongerVar = 200; // comment 2

MyStruct arrayOfMyStruct[] = 
{   
    // Name, timeout, valid
    {"A string", 1000, true},// Comment 1
    {"Another string", 2000, false }, // Comment 2 
    {"Yet another string", 11111000,false}, // Comment 3
    {NULL, 5, true }, // Comment 4
};
Prembo
  • 2,186
  • 2
  • 28
  • 48
  • 6
    This issue with this, is that when one line gets too long, (say you have to add "Yet another string, but this one is longer than the rest"), you either have to break the nice pattern, or reformat everything, leading to a source control nightmare where every line changes. – Eclipse Mar 24 '10 at 19:32
  • You may want to have a look at the Align plugin for Vim. – StackedCrooked Jan 05 '11 at 15:15
14

Public Top - Private Down

A seemingly small optimization, but ever since I switched to this convention, I have a way more fun time to grasp my classes, especially after I haven't looked at them for 42 years.

Having a consistent member visibility, going from points of frequent interest down to the boring stuff, is extremely helpful, especially when the code ought to be self-documenting.

(sidenote for qt-users: slots come before signals because they should be callable like non-slot member functions, and apart from their slottyness be indistinguishable from non-slots)

  • Public, protected, private
  • then Factory, ctor, dtor, copying, swapping
  • then the class' Interface At the very last, in a seperate private: section, comes the data (ideally only an impl-pointer).

This rule also helps a ton if you have problems keeping your class declaration uncluttered.

class Widget : public Purple {
public:
    // Factory methods.
    Widget FromRadians (float);
    Widget FromDegrees (float);

    // Ctors, rule of three, swap
    Widget();
    Widget (Widget const&);
    Widget &operator = (Widget const &);
    void swap (Widget &) throw();

    // Member methods.
    float area() const;

    // in case of qt {{ 
public slots:
    void invalidateBlackHole();

signals:
    void areaChanged (float);
    // }}

protected:    
    // same as public, but for protected members


private:    
    // same as public, but for private members

private:
    // data
    float widgetness_;
    bool  isMale_;
};
Sebastian Mach
  • 36,158
  • 4
  • 87
  • 126
11

In if statements, when there are difficult conditions, you can clearly show which level each condition is using indentation.

if (  (  (var1A == var2A)
      || (var1B == var2B))
   && (  (var1C == var2C)
      || (var1D == var2D)))
{
   // do something
}
Fund Monica's Lawsuit
  • 5,770
  • 8
  • 46
  • 65
zerbp
  • 283
  • 1
  • 3
  • 9
  • 3
    Spelling errors and typos also get corrected in code that I work on! – Mark Kegel Nov 10 '08 at 00:56
  • 5
    If this was my code I would put the two || conditions on the same line, but split the && conditions as you have done, resulting in a 2 line if statement. – jussij Nov 11 '08 at 23:16
8

Compile-time polymorphism

(Also known as syntactic polymorphism and static polymorphism, contrast with runtime polymorphism.)

With template functions, one can write code that relies on type constructors and call signatures of families of parametrized types, without having to introduce a common base class.

In the book Elements of Programming, the authors refer to this treatment of types as abstract genera. With concepts one can specify the requirements on such type parameters, though C++ doesn't mandate such specifications.

Two simple examples:

#include <stdexcept>

template <typename T>
T twice(T n) {
  return 2 * n;
}

InIt find(InIt f, InIt l,
          typename std::iterator_traits<InIt>::reference v)
{
  while (f != l && *f != v)
    ++f;
  return f;
}   

int main(int argc, char* argv[]) {
  if (6 != twice(3))
    throw std::logic_error("3 x 2 = 6");

  int const nums[] = { 1, 2, 3 };
  if (nums + 4 != find(nums, nums + 4, 42))
    throw std::logic_error("42 should not have been found.");

  return 0;
}

One can call twice with any regular type that has a binary * operator defined. Similarly, one can call find() with any types that are comparable and that model Input Iterator. One set of code operates similarly on different types, with no shared base classes in sight.

Of course, what's really going on here is that it's the same source code being expanded into various type-specific functions at template instantiation time, each with separate generated machine code. Accommodating the same set of types without templates would have required either 1) separate hand-written functions with specific signatures, or 2) runtime polymorphism through virtual functions.

seh
  • 14,430
  • 2
  • 48
  • 57
7

No favorites but I will fix code that has:

  1. tabs - causes misalignment in many IDEs and code review tools, because they don't always agree on tab at mod 8 spaces.
  2. lines longer than 80 columns - let's face it, shorter lines are more readable. My brain can parse most coding conventions, as long as the lines are short.
  3. lines with trailing whitespaces - git will complain about it as whitespace errors, which show up as red blobs in diffs, which is annoying.

Here is a one-liner to find the offending files:

git grep -I -E '<tab>|.{81,}|  *$' | cut -f1 -d: | sort -u

where <tab> is the tab character (POSIX regexp doesn't do \t)

ididak
  • 5,534
  • 1
  • 18
  • 21
  • 7
    Well TAB characters should be used for indenting, not formatting. Spaces should be used for formatting. That way the code will show up nicely with any TAB width setting. And TABs should be 8 characters anyway. – Terminus Nov 11 '08 at 11:23
  • Heh... Trailing whitespace is so annoying! I have to bite my tongue whenever I'm watching someone code and they leave in spaces at the end of the line (say, when breaking a line by putting the cursor after a space and hitting Enter). – Owen Dec 18 '08 at 07:53
  • The problem with trailing whitespace is you can't see it. – FryGuy Jan 14 '09 at 22:47
7

re: ididak

I fix code that breaks long statements into too many short lines.

Let's face it: it's not the 90's any more. If your company can't afford widescreen LCDs for its coders, you need to get a better job :)

  • 3
    Even if your monitor wrapped all the way around your head, shorter lines would be easier for you to take in. Let the code context determine if the line needs to be long; usually it doesn't. – Mark Ransom Nov 09 '08 at 22:39
  • 10
    I put multiple windows side by side on wide screens. I'd like to be able to (read) code on a laptop as well. – ididak Nov 10 '08 at 00:08
  • Most of the time, it shouldn't be necessary to see all of that really long line to understand at a glance what it does. – korona Nov 11 '08 at 10:49
  • Okay, let's make it 120 and call it a deal :) – utku_karatas Nov 11 '08 at 11:00
  • 7
    You get my +1 vote. There are times when wrapping long lines does help, but to automatically wrap a line just because it hits the 80 column mark is just stupid. – jussij Nov 11 '08 at 23:17
  • Too long lines in books is a good reason for me to not read the book. It's not 90's anymore, true, but since then, human had not have so much time to evolve so that the brain is not annoyed by too long lines. – Sebastian Mach Jun 21 '11 at 11:33
  • Minus here. As ididak already said, there is sometimes a need to have several windows of code on one screen, side by side. Consider code compare/merge utils. Your "fixes" will remind people all the conveniences of horizontal scrolling. – Alex Che Dec 27 '13 at 10:31
  • Side-by-side buffers (I usually have three), diffs (in terminals, gitk, web interfaces such as github, ...), difficulty for my eyes to jump from a row to the next one and land at the right place, warning that your code has too many levels of indentation and needs refactoring (rationale for linux kernel to use 80 limit and 8-space tabs), ... – Gauthier Jun 28 '16 at 09:28
6

if/while/for parenthesized expression(s) WITH a space separator

if (expression)  // preferred - if keyword sticks out more

vs.

if(expression)  // looks too much like a void function call

I guess this implies that I like my function calls to NOT have a space separator

foo(parm1, parm2);
franji1
  • 2,685
  • 2
  • 19
  • 39
  • 2
    For what it's worth, the [llvm coding standard](http://llvm.org/docs/CodingStandards.html#micro_spaceparen) agrees with you, but lists it in the "Microscopic Details" section. – Stuart Berg Jan 07 '12 at 20:41
5

Template and Hook

This is a way to handle as much as possible in a framework and give a door or hook for customization by users of a framework. Also known as Hotspot and Template Method.

class Class {
  void PrintInvoice();     // Called Template (boilerplate) which uses CalcRate()
  virtual void CalcRate() = 0;  // Called Hook
}

class SubClass : public Class {
  virtual void CalcRate();      // Customized method
}

Described by Wolfgang Pree in his book Design Patterns for Object-Oriented Software Development.

epatel
  • 44,965
  • 17
  • 105
  • 143
  • 1
    Herb Sutter makes a strong case that virtual methods should usually be *private*, since this allows the base class to enforce invariants (like always executing derived class methods in a certain order): http://www.gotw.ca/publications/mill18.htm – j_random_hacker Jun 26 '12 at 12:58
5

After working with someone who was partly blind - and at his request - I switched to using many more spaces. I didn't like it at the time, but now I prefer it. Off the top of my head, the only place where there isn't whitespace between identifiers and keywords and whatnot is after a function name and before the following parentheses.

void foo( int a, int b )
{
  int c = a + ( a * ( a * b ) );
  if ( c > 12 )
    c += 9;
  return foo( 2, c );
}
Jamie Hale
  • 1,509
  • 2
  • 9
  • 21
4

I don't know if it qualifies as an idiom, exactly, but quite a bit of heavy-duty template programming depends (often heavily) on SFINAE (substitution failure is not an error). A couple of the answers to a previous question have examples.

Community
  • 1
  • 1
Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035
  • 1
    I think it qualifies as an idiom. Whether it is among the "most useful" is debatable though. Most C++ programmers probably don't need it very often. Still, +1 from me. – jalf Jan 09 '10 at 19:07
  • Combine with showing how boost::enable_if is useful. –  Jan 09 '10 at 19:13
4

Not sure if this counts as an idiom, but I tend to use doxygen-style inline comments even when the project isn't -yet- using doxygen...

bool MyObjects::isUpToSomething() ///< Is my object up to something 

(aside. my comments are not usually quite that lame.)

albert
  • 5,966
  • 3
  • 13
  • 29
Roddy
  • 63,052
  • 38
  • 156
  • 264
4

I really like putting a small statement on the same line as an if

int myFunc(int x) {
   if(x >20) return -1;
   //do other stuff ....
}
boycy
  • 1,433
  • 12
  • 24
mempko
  • 308
  • 2
  • 8
  • 3
    Yep, good for guard clauses. Nevertheless I always put curly braces around the conditional statement. It has proven to be more maintainable for me. – foraidt Nov 11 '08 at 12:42
  • 1
    I generally don't use the curly braces if I'm doing it all on one line. If the line ends up long enough that I want to break it, though, I add the braces. – Adam Jaskiewicz Nov 11 '08 at 23:12
  • Even more readable would be: `return -1 if x > 20;` – Pasha May 21 '13 at 19:12
  • 5
    More readable maybe, but it's not C++.. – boycy Aug 12 '14 at 08:57
  • Generally I disagree with this suggestion, as it makes debugging (stepping thoriugh code step by step) a little more difficult - because there are times I don't know if that line was executed. I have to put more thought (mind power) into analyzing the code, to see what is happening. With multiline I don't have to analyze I just see that the code steps "in" or "over" and if it's not as expected I only then start to analyze. – Robert Andrzejuk May 20 '17 at 00:44
2

Document the return values on the function line, so they are very easy to find.

int function(void) /* return 1 on success, 0 on failure */ 
{
    return 1;
};
EvilTeach
  • 26,577
  • 21
  • 79
  • 136
  • 12
    Putting a superfluous semicolon at the end of a block that doesn't need a semicolon is one of my least favorite C++ coding style idioms. – bk1e Nov 09 '08 at 18:39
  • This style suggestion doesn't help on anything but the simplest return values. – Austin Ziegler Nov 18 '08 at 19:19
  • Nonsense. You can make the comment as large or small as necessary. When the question arises, "What does this thing return?" where do you go? users guide? hpp file? cpp file? If you go look at the function, it's right there. Most IDEs can pick the comment up and show it to you in context. – EvilTeach Nov 23 '08 at 14:52
  • 1
    Reading thorough the code trying to figure out what a function returns is a squandering of developer time. Do everyone a favor, comment your return values, in a place that is easy to find. – EvilTeach Nov 23 '08 at 14:54
  • Doesn't the code need a pair of parentheses `()` after `function`? – Arun Oct 22 '10 at 19:59
  • @evil you sound like one can put the comment also one line before the function line in your comment. but in your answer you say that this idiom comprises putting the comment exactly at the function line. hence you would only have one line available to document complex return value computations. – Johannes Schaub - litb Mar 03 '12 at 18:35
  • Ya, for simple stuff it works. There isalso a strong pull, to put it in front of the function, so that msvc can see it and pick it up. – EvilTeach Mar 03 '12 at 21:58
2

It's useful to put function names on a new line, so you can grep like

grep -R '^fun_name' .

for them. I've seen that style used for a loads of GNU projects and like it:

static void
fun_name (int a, int b) {
    /* ... */
}
Johannes Schaub - litb
  • 466,055
  • 116
  • 851
  • 1,175
  • 1
    An alternative that doesn't require this convention: `egrep -r 'main\([^)]*\)\s?\{' .` – admittedly, not nearly as simple, and requires arguments and opening brace on the same line. – Konrad Rudolph Nov 11 '08 at 22:55
  • 2
    Maybe it's time to write a special grep for C++ code that uses libclang for parsing. –  Mar 03 '12 at 14:58
1

I'd suggest PIMPL or as James Coplien originally called it "Handle Body".

This idiom allows you to completely decouple interface from implementation. When working on the rewrite and re-release of a major CORBA middleware component, this idiom was used to completely decouple the API from the implementation.

This practically eliminated any possibility reverse engineering.

An excellent resource for C++ idioms is James Coplien's excellent book "Advanced C++ Programming Styles and Idioms". Highly recommended!

Edit: As pointed out below by Neil, this book is quite out of date with many of his recommendations actually being incorporated into the C++ standard itself. However, I still find it to be a source of useful info, esp. in the form of his PLoP paper on C++ idioms where many idioms were recast into patterm form.

Rob Wells
  • 34,617
  • 13
  • 76
  • 144
  • The book is completely out of date and has little relevance to modern C++ programmers. –  Jan 09 '10 at 18:23
  • That's James Coplien. The handle/body idiom, while certainly similar wasn't generally used the same way or for the same reasons. It was primarily for reference counting. – Jerry Coffin Jan 09 '10 at 18:26
  • 2
    I missed the Douglas Coplien mistake - that is actually quite funny. I'd pay to read Microserfs re-written to refer to the original C++ devs! –  Jan 09 '10 at 18:28
  • Given that current implementations of C++ are supposed to be reverse compatible with previous implementations, I think your statement of "completely out of date and has little relevance to modern C++ programmers" to be a bit of an exaggeration. There's still plenty in that book to be useful. Yikes. Must've mixed up Doug Coupland with Cope. – Rob Wells Jan 09 '10 at 18:58
  • @Rob Coplien's book came out nearly 20 years ago, long before the language was standardised, and the standard made no guarantees that it was compatible with older implementations - in many was it explicitly wasn't. Also, many of the idioms Coplien mentions have been subsumed into language features, like templates. –  Jan 09 '10 at 19:03
  • @Neil, I agree so I've added a note about the age of the book and a link to his '98 update to the book. – Rob Wells Jan 09 '10 at 19:13
  • 1
    @Neil: I can't say I completely agree. Quite a bit of code in the book depends on templates (though its use is pretty "tame" by modern standards). The biggest part that's obsolescent is its pervasive use of reference counting. I'd say around 2/3rds of the idioms in the book apply as well today as ever (though you'd often implement them somewhat differently today). – Jerry Coffin Jan 09 '10 at 19:19
  • @Jerry Use of templates first appears at page 259 (they are mentioned briefly prior to this) which is about 2/3rds of the way through the main text, and the example is as you say "tame", some may say "naive". But I suppose I must declare that I've never liked this book, and this long-term dislike my be coloring my view. I still find it very difficult to imagine recommending it to a new C++ programmer in 2010. –  Jan 09 '10 at 19:27
1

Write each method or function argument on a separate line such that it can be easily commented.

int ReturnMaxValue(
    int* inputList,   /* the list of integer values from which to get the maximum */
    long size,        /* count of the number of integer values in inputList */
    char* extraArgs   /* additional arguments that a caller can provide.    */
)
Ather
  • 1,600
  • 11
  • 17
  • 3
    Use meaningful variable names rather than comments: int ReturnMaxValue(int *inputList, long inputListSize). The comment about extraArgs told me just about as much as the variable name - nothing (yeah, I know it's just an example but it's not a really good one). – Andreas Magnusson Nov 10 '08 at 11:10
  • Completely concur with Andreas. If you really need to be documenting your parameters, use Doxygen format. – Austin Ziegler Nov 18 '08 at 19:18
0

I always nitpick and edit the following:

  • Superfluous newlines
  • No newline at EOF
korona
  • 2,210
  • 1
  • 22
  • 37
0

I usually stick to KNF described in *BSD STYLE(9)

Terminus
  • 894
  • 2
  • 10
  • 21
-1

I tend to put an else on all of my ifs.

if (condition)
{
    complicated code goes here
}
else
{
    /* This is a comment as to why the else path isn't significant */ 
}

Even though it annoys my coworkers. You can tell at a glance, that I considered the else case during coding.

EvilTeach
  • 26,577
  • 21
  • 79
  • 136