Monday, September 17, 2007

Omit Needless Words (in C++)

I came across a small C++ language feature which I didn't know about. It is a very simple syntactic sugar for omitting needless words. Many of you may already know it but to those who don't I say: read this short blog entry

Omit Needless Words (in C++)


After I shared this with my colleagues I asked them "So can you think of any other situation when the ThisClass typedef in a class is obligatory,... apart from generic programming?" They laughed and said that I had just asked a question "Can something be useful for any other thing than the only one it is useful for?" I was left with my doubts. Can you, readers, prove that wrong? :)

12 comments:

Parceval said...

Typedefs just by themselves are wrong - programmer should at least try to envision if they are needed, or not - like in that case.
If they aren't needed, then they must not be used, since they make code not-so-local, which is obviously bad.

Marya said...

I didn't quite get your point here. What do you mean by saying "typedefs make the code not-so-local"? Maybe an example could help :)

Parceval said...

If the typedef is used only once, it is almost useless, right?
By non-local I mean that if you want to change something about the code, using your typedef and probably must go and change the typedef itself too. And it is not right here, where the code that uses it is. It is somewhere else - i.e. it is not local.

Marya said...

The typedefs reduce the number of places you need to change the code to one particular place - the typedef itself. Lets say you have a vector of Item* in your class. In all your methods you used that vector to iterate it or find something in it or whatever. In some moment you decide to switch to a vector of const Item* or even a list of const Item*. Now if you had a typedef for that and referred to it everywhere when you worked with your collection instance, then you need to change only in one place - the typedef itself. If you didn't, well... I feel there is no need to explain it. :) It is so obvious. I've done this so many times that I cannot imagine not typedefing my collection types inside a class or wherever.
Even if a typedef is used only once, it can still be useful.

Marya said...

But I didn't meant for this post to be a discussion of the usefulness of typedef. I wanted a discussion of the ThisClass typedef.

Parceval said...

Since inside the class definition / declaration you don't need that typedef - it is quite useless, right?

Marya said...

No, it's not.

Parceval said...

Why?

Stefan said...

Let's suppose
(for the sake of discussion) that we have the following class.


class CollectionOps
{
public:
vector<int> collection;
bool HasElementsGreaterThan(int howmuch);
int GetCountOfEvenElements();
};


The member functions do what their names suggest by iterating our collection through a vector<int>::const_iterator. Now, imagine that you want to change the underlying container to be a set<int>. That would require a change to the member 'collection' and, also, everywhere an iterator over a vector<int> is used.

by typedef-ing our sequence we get:


class CollectionOps
{
public:
typedef vector<int> Collection;
Collection collection;
bool HasElementsGreaterThan(int howmuch);
int GetCountOfEvenElements();
};


Now, all methods operate through Collection::const_iterator and should the container type change, the methods will remained unmodified.

As you should see, the typedef helped us separate concerns about which container to use and how we use it.

Parceval said...

Fair point.
However, I can't recall the last time I changed a container type without retouching the code that uses it.

Marya said...

Stefan, my point exactly. :)
Parceval, sure you need to touch the code when changing the collection type, their interfaces are usually different. But still the places where the code needs to be changed are much fewer than in the other case. But really: typedefs ARE useful. And gain: this wasn't the purpose of this post..

Stefan said...

Of course. The point is, that the typedef provided us with separation of concerns - container type vs. iteration. However this is only useful when there is a common interface between the container classes. In our case there is - the iterators. In your case, for example, insertion into the sequence may have caused the retouching.

Further abstraction can be achieved through the Adapter pattern, but that's a topic for another post.