Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I've always had a bit more luck with the "typedef each step of the construction" rule-of-thumb. Also, I tend to hide anything as complex as "pointer-to-array-of-pointers-to-functions" (even though you memorize this idiom pretty quickly after an hour in the kernel) behind library ADT's, so you're never indexing an array, but rather passing an index and a whatever_t* to whatever_get(w, index).


That's a good approach, but sometimes you can't do it in C++. (At least with C++03.) Consider:

  template <class T>
  T* new_align_1d(size_t d1, unsigned int align)
  {
    void* ptr = _malloc_align(d1 * sizeof(T), align);
    return new (ptr) T[d1];
  }
So, I'm defining a function new_align that takes a size and an alignment. I allocate enough space for a 1-dimensional array of the given size on that alignment, then use the placement operator to construct the actual objects in that place. Then return the pointer. Pretty straightforward. So let's generalize one dimension up:

  template <class T, size_t d2>
  ? new_align_2d(size_t d1, unsigned int align)
  {
    void* ptr = _malloc_align(d1 * d2 * sizeof(T), align);
    return new (ptr) T[d1][d2];
  }
You can probably see what I'm doing here. So what's the return type? And what's the syntax for specifying it? Since it's a template, we can't define a typedef to help us. (C++0x should allow that with parameterized typedefs.) The answer surprised me - I really had to look at the grammar and mechanically figure out what it was going to be.

(Yes, I have to pass d2 as a template parameter - it's part of the type of the array and must be known at compile time.)


The fact that I instantly recognized this problem case (having had it many times myself) makes me sad.

I'm so incredibly happy that 95% of the code I write now is in Python.


This is a Good Idea, but it doesn't help you understand other people's code if they don't follow it. Hence the need for a mnemonic rule.


A coworker introduced me to the ADT-style solution for nesting problems, and it works nicely. He introduces a struct that encapsulates any nested inner collection. It's worth noting his designs use fat structs in a shallow hierarchy.

This has an added advantage (and burden) when calling the code. Since you access a field inside of the struct, you write extra names. The claim is that myList[0].fnList[0].fn(3) is more readable than myList[0][0](3). This can get cluttered with lots of nesting, but this kind of nesting usually screams "refactor me!" anyways.

I prefer a mix: make the common inner collections into data types, and typedef the rest. Doing it all the time creates too many little structs for my liking.


The second approach, that's what I like...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: