3

Possible Duplicate:
What are your favorite C++ Coding Style idioms

Dear C++ fans,

Could you list here your favorite C++ idioms? It is better to list those which are useful yet not well-known.

Firstly, I put one of mine:

To avoid tedious repeating for (size_t i = 0; i < n; ++i) {...} , I use a macro like this:

#define LOOP(n) for (size_t _i = 0; _i < n; ++_i)

_i is a placeholder as bind uses.

So I can write:

vector<int> coll(100);
LOOP (100)
{
    coll[_i] = _i;
}

LOOP (100)
{
    auto a = _i;
    LOOP (100)
    {
        auto b = _i;
        cout << a << b;
    }
}
Community
  • 1
  • 1
xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 6
    Re your exmaple: That's something your IDE should help you with, not obscure macros. – Mchl Dec 12 '10 at 11:50
  • @Mchl, I think LOOP can more clearly express my intent here. – xmllmx Dec 12 '10 at 11:52
  • 9
    +1 for a decent question, but -1 for a terrible, terrible example. Net zero vote :) – NPE Dec 12 '10 at 11:53
  • @aix, I think macro is not always evil in C++ world. – xmllmx Dec 12 '10 at 11:55
  • Now who the hell has voted to close this one? Something's really wrong with guys out there. x-( – Prasoon Saurav Dec 12 '10 at 11:58
  • 1
    There are probably plenty of duplicates: http://stackoverflow.com/questions/1759613/what-c-idioms-should-c-programmers-use, http://stackoverflow.com/questions/2096515/listing-elegant-c-idioms-closed, http://stackoverflow.com/questions/2345177/basic-c-idioms-techniques. The OP's example is probably more of a *personal* idiom, not a universally accepted C++ idiom? – UncleBens Dec 12 '10 at 12:21
  • 1
    @UncleBens, Yes, that is my personal idiom. I think personal idioms which are not well-known may be more interesting. – xmllmx Dec 12 '10 at 12:28
  • 1
    What if you need two nested for loops? Using your macro, the placeholder vars would clash. – mingos Dec 12 '10 at 12:53
  • @mingos, LOOP (100) { auto a = _i; LOOP (100) { auto b = _i; cout << a << b; } } – xmllmx Dec 12 '10 at 13:32
  • @xmllmx, OK, but this syntax is cryptic. I prefer to write my loops explicitly: `for(int i=0;i<100;++i) for(int k=0;j<100;++j) { ... }` - other people will always know what it is. – mingos Dec 12 '10 at 13:39
  • @mingos, LOOP is not intended to be used everywhere. It is just useful for simple and count-fixed loops. – xmllmx Dec 12 '10 at 13:44
  • @xmllmx, maybe it's just me, but I find it confusing nonetheless. – mingos Dec 13 '10 at 00:28

4 Answers4

9

RAII is on the top of my list. There are so many cases when it just comes in handy...

Most useful as a generic implementation like Andrei Alexandrescu's libloki.

Marcus Borkenhagen
  • 6,536
  • 1
  • 30
  • 33
5

SFINAE

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
4

RAII + opening a nested block if exact lifetime scope needed:

Lock lock(this);
ResourceHolder resource(findResource());
WorkerHolder worker(resource);
if (!worker)
    return false; // frees the resource and unlocks the lock
{
    WorkAssignment assignment(worker);
    assignment.Execute();
} // assignment cleaned up even in case of exception
...
Vlad
  • 35,022
  • 6
  • 77
  • 199
4

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.

AshleysBrain
  • 22,335
  • 15
  • 88
  • 124