"Training a monkey would be easier"

Are you using :make within vim? If you are, then you probably noticed that getting lots of compiler errors is not uncommon, and that vim has a tendency of jumping to the first error found… but what happens if you want to see subsequent errors too, because you’re a really crappy programmer and need to find the 10 or 20 errors you just introduced with your single line edit?

Luckily Vim is always the anwser, just use cnext and cprev until you reach the error you are looking for.

Quite a progress I’d say, as these are mostly programs I use which don’t come in the default install (even though they should). You know, I even have hopes for the sound system in my notebook this time…

There are two well known macros from the preprocessor which every macro-sorcer must know. They are __FILE__ and __LINE__. You probably already know about them but anyway, __FILE__ will give you the current file and __LINE__ the current line. Easy, huh?

int main() {
printf("%s : %i", __FILE__, __LINE__);
return 0;
}

The program above would give you “main.cpp : 3” as a result. There is nothing going on at execution time, it’s all preprocesor wizardy. In fact with “g{++/cc} -E” you can even check what the “real” output is (-E means to return the preprocessor output. Keep in mind a lot of stuff will be included from the headers you use).

int main() {
printf("%s : %i", "main.cpp", 3);
return 0;
}

Well that’s nice and all, but g++ can top this easily:

int main() {
std::cout << __PRETTY_FUNCTION__ << "n";
return 0;
}

There are a couple of notable things about this new “pretty function” thing:

1. It will demangle a function’s name

2. This time it isn’t a preprocessor secret thing but a real variable g++ will create.

You can easily use this for better logging functions now (with some macro wizardy, obviously).

So far we’ve learned the basic constructs of template metaprogramming (loops, branching, return values) and some basic list operations (getting the length of a list, appending and prepending elements, checking if an element is included in a list). Let’s put it all together by creating an operation to return the position of an element. It’ll be very useful later on too.

If we go back to the Includes operation we can get some help to define the Position operation: the position of an element in a list is one plus the position of the element we’re searching for in the tail, or zero if the head equals said element. The operation is not defined if the element is not in the list.

Looks easy… but doesn’t work. First problem, we can’t compare two types, remember? We need to use Eq<X, Y> again. Second problem, although we said the operation is undefined if the element is not included on the list, it would be nice if we could force the compiler to fail if (or when) that happens. Let’s rewrite the operation using a façade again, but adding an Assert:

Oh, we haven’t defined assert yet! There’s another problem, too: even if it won’t compile, the compiler will try to expand _Position< …, NIL > indefinitely, causing an error after too many nested template calls. Not nice. We need to add a case to make the compiler stop:

All that code for such a simple operation, man. Also, see what we did with Assert<>? It seems making a compile fail is actually quite easy. That’s what I have most experience with.

We’ve been through quite a lot, and our toolboox should be quite big already. Next time we’ll start steering towards some sort of applicability, trying to use some of all these stuff to implement a real, useful and working program… assuming that’s even possible.

An interesting topic for a change: is Linux binary portable? That is, can we take a binary file and be sure it’ll run in any other Linux system? What happens if we broaden that to any POSIX system, will it blend? Eh, I mean, will it run?

Doing some research on the subject I wrote down a list of the thought process which led my to an (inconclusive) answer:

1. First we should define what a binary is for us: When we talk about a binary we are usually thinking about a compiled binary file, not an interpreted script file like Ruby or Python. Those are for people who like things to actually work, so let’s focus on a compiled executable file, like a C/C++ application.

2. Defining compiled file: What could it be other than a sequence of bytes the microprocessor can understand? Yes, that’s right, it’s sort of interpreted code, only there’s electronics behind, not more code. This brings us to the first interesting conclusion: the executable must be (leaving emulators aside) compatible with the architecture you’re on. Running Sparc? Well then, the binary better be compiled for Sparc because otherwise to the uP will not make any sense.

3. Format: as any other thing, a binary file must have a format. That is a standard which defines the structure the file will follow. ELF is the binary format for Linux and it’s quite standard. Of course, if the binary format is a standard then we should get perfect portability between different platforms running on equal architecture. Unfortunately that’s not the case.

4. (Cont’d) Why don’t we? The binary depends not only on compile time “stuff” but a loading time linking occurs: the executable binary will get linked with the system files like glibc, or any other dependency on a shared library it may have.

So, what are the keypoints for Linux binary portability? Architecture, binary format and system libraries.

Of course, making the executable run is only part of the equation, as running and segfaulting on the spot is not so nice either. For this last part you’ll have to closely follow the standards defined by POSIX for paths and stuff like that.

Epilogue

As an epilogue, we could add that Windows binary compatibility tends to be great. Running binaries from 12 years back is no small feat, yet this leads to a whole lot of other problems: an incredible complex loader, security bugs, backwards compatibility headaches, et al. The old new thing is a great source of information for this topics, I’m quite illiterate about Windows binaries nowdays 🙂

So, you are an uber console geek, using only vim and the command line to compile all your projects, execute the tests, blah blah blah… if only you could squeeze that microsecond lost whenever you switch from vim to compile you’d be 1e-4 seconds more productive… oh, wait, you can!

Whenever you think you’re project is good enough to compile just hit :make to be proven wrong. Type :make test to run your tests (because you are using TDD, aren’t you?) and watch all those red flags fly by.Also, add the following mapping to your ~/.vimrc for an extra happy coding session:

Appending is a little bit more difficult, as we need to first find the end of the list. Think for a second how would you define it… back? Ok, I’d define it this way: appending an element to the list yields a list, consisting of the same head and the result of appending said element to the tail. The null case, as usual, is appending an element to a NIL list; in this case the result is a list with the element itself. So:

I promised to add one more operation to our toolbox, returning the position of an element, but this post is getting quite long and I’m afraid it may be too much for the average attention span of a programmer… we’ll leave it for next time.

Remember last time? We learned how to get the lenght of a list. This time I’ll introduce some more of these basic ops. Let’s begin with “Nth”: getting the Nth element of a list; which, remember, in this case is a type, not a concrete element. This means the Nth element will be something like int, char, const char*, not 1, 2 or 3. We introduced a trick to get around this limitation before using a template <int>, go there to refresh your memory if needed.

So, what would the coloquial definition of “Nth” be? I’d put it like “The operation Nth for a list equals the head of the list for N = 0 and Nth (minus one) of the tail otherwise”. A little bit more formally:

Nth(0, lst) <- lst.head
Nth(n, lst) <- Nth(n-1, lst.tail)

Translating this to C++ should be a breeze to you now. Try it, I’ll wait. Read? OK, this is MY answer:

Though the structure is very similar to the previous “basic operation”, getting the length of a list, the concept is quite different. This time we’re defining a return type recursively. Anyway, it was too easy indeed, let’s try a more complex operation now.

How can we check if an element exists on a list? Seems easy enough, an element is included in a list if the head equals the element itself or if the element is included in the tail. In the pseudo language I just invented:

Looks nice, doesn’t it? Too bad it won’t work, you can’t compare two types. What would (int == char) mean in C++? We need a helper there, some kind of trick to compare two types. We can use partial template specialization again: