What Are Your Favorite C++ Coding Style Idioms

What are your favorite C++ Coding Style idioms

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).

What are your favorite C++ idioms?

Good question but I think your example is a bad one! Your LOOP macro does not make anything clearer - it actually hides your intent from programmers who don't use your macro, and it doesn't even look like C++ - my first reaction to your snippet would be "is that even C++?" or "what's wrong with an ordinary for?". It may be tedious to write the loops over and over, but we all know everyone spends a lot more time reading and maintaining code than writing it in the first place, so it's hardly a waste of time writing out a full for, and it's much clearer. You can continue to argue your point, but you should be aware that using macros in that way is not a widely accepted technique - other people looking at your code will call you out on it too.

Anyway, to add an actual answer - my favourite idiom in C++0x is a vector of unique_ptr:

std::vector<std::unique_ptr<T>> my_container;

It has the following advantages - essentially a safe vector of pointers:

  • It provides random access in O(1) time
  • Elements are guaranteed to never move in memory even when reallocating (so you can safely take the address of Ts and store them)
  • Fast for tasks like sorting (just shuffling some pointers, not copying heavyweight objects)
  • Exception safe and helps prevent memory leaks - erase() on an element also releases the memory
  • Flexible - you can std::move() pointers out of the container and put them somewhere else

It does have one or two disadvantages:

  • Each element is allocated on the heap which may have performance implications if adding/removing a lot of elements, plus elements can be far apart in memory losing cache locality
  • Iteration requires double indirection (*i)->member syntax - but I don't think it's a big deal

However, especially for heavyweight objects, I think it is nearly an ideal container.

Any good idioms for error handling in straight C programs?

Two typical patterns:

int major_func()
{
int err = 0;

if (err = minor_func1()) return err;
if (err = minor_func2()) return err;
if (err = minor_func3()) return err;

return 0;
}

int other_idea()
{
int err = minor_func1();
if (!err)
err = minor_func2();
if (!err)
err = minor_func3();
return err;
}

void main_func()
{
int err = major_func();
if (err)
{
show_err();
return;
}
happy_happy_joy_joy();

err = other_idea();
if (err)
{
show_err();
return;
}
happy_happy_joy_joy();
}

What is a programming idiom?

A programming idiom is the usual way to code a task in a specific language. For example a loop is often written like this in C:

for (i=0; i<10; i++)

PHP will understand a similar construct:

for ($i = 1; $i <= 10; $i++)

But it is discouraged in PHP for looping over an array. In this case you would use:

foreach ($arr as $value)

Whereas in Ruby, you would use:

(1..10).each

for the loop, or:

array.each

There are many many possibilities to write a loop in those languages. Using the idiom makes it immediately identifiable by experienced readers. They can then spend their time on more important problems.

Idiom vs. pattern

Contrary to the idea that patterns are language agnostic, both Paul Graham and Peter Norvig have suggested that the need to use a pattern is a sign that your language is missing a feature. (Visitor Pattern is often singled out as the most glaring example of this.)

I generally think the main difference between "patterns" and "idioms" to be one of size. An idiom is something small, like "use an interface for the type of a variable that holds a collection" while Patterns tend to be larger. I think the smallness of idioms does mean that they're more often language specific (the example I just gave was a Java idiom), but I don't think of that as their defining characteristic.

What are some C++ related idioms, misconceptions, and gotchas that you've learnt from experience?

I've liked this since the time i've discovered it in some code:

assert(condition || !"Something has gone wrong!");

or if you don't have a condition at hand, you can just do

assert(!"Something has gone wrong!");

The following is attributed to @Josh (see comments). It uses the comma operator instead:

assert(("Something has gone wrong!", condition)); 

Which C++ idioms are deprecated in C++11?

  1. Final Class: C++11 provides the final specifier to prevent class derivation
  2. C++11 lambdas substantially reduce the need for named function object (functor) classes.
  3. Move Constructor: The magical ways in which std::auto_ptr works are no longer needed due to first-class support for rvalue references.
  4. Safe bool: This was mentioned earlier. Explicit operators of C++11 obviate this very common C++03 idiom.
  5. Shrink-to-fit: Many C++11 STL containers provide a shrink_to_fit() member function, which should eliminate the need swapping with a temporary.
  6. Temporary Base Class: Some old C++ libraries use this rather complex idiom. With move semantics it's no longer needed.
  7. Type Safe Enum Enumerations are very safe in C++11.
  8. Prohibiting heap allocation: The = delete syntax is a much more direct way of saying that a particular functionality is explicitly denied. This is applicable to preventing heap allocation (i.e., =delete for member operator new), preventing copies, assignment, etc.
  9. Templated typedef: Alias templates in C++11 reduce the need for simple templated typedefs. However, complex type generators still need meta functions.
  10. Some numerical compile-time computations, such as Fibonacci can be easily replaced using generalized constant expressions
  11. result_of: Uses of class template result_of should be replaced with decltype. I think result_of uses decltype when it is available.
  12. In-class member initializers save typing for default initialization of non-static members with default values.
  13. In new C++11 code NULL should be redefined as nullptr, but see STL's talk to learn why they decided against it.
  14. Expression template fanatics are delighted to have the trailing return type function syntax in C++11. No more 30-line long return types!

I think I'll stop there!

What is idiomatic code?

Idiomatic means following the conventions of the language. You want to find the easiest and most common ways of accomplishing a task rather than porting your knowledge from a different language.

non-idiomatic python using a loop with append:

mylist = [1, 2, 3, 4]
newlist = []
for i in mylist:
newlist.append(i * 2)

idiomatic python using a list comprehension:

mylist = [1, 2, 3, 4]
newlist = [(i * 2) for i in mylist]


Related Topics



Leave a reply



Submit