Nicolás Brailovsky


A modern blog

Archive for the ‘Templates’ Category

Cool C++0X features I: Intro

author Posted by: nico on date Apr 18th, 2011 | filed Filed under: C++0x, Templates

C++0X brings some very cool changes, and I wanted to start a series of posts regarding some of these changes, with a small explanation of each new feature (that I currently understand, at least), an example of its usage and why I think it’s a cool thing. Notice these two may be mutually exclusive, some of these may just be cool but I wouldn’t recommend using them on a day to day basis. An example of a very cool feature which I wouldn’t normally use in a project is the one I want to write about today: variadic templates.

"C++ gives you enough rope to shoot yourself"

What’s not to love about variadic templates? Its name implies (correctly) that it uses templates, and it also has a “variadic” thingy, which you can use to look smart since no one really knows what it means.

Templates themselves can quickly get complicated if used by unexperienced padawans in the art of martial C++, yet their hypnotic beauty draws every programmer to use them just like flies are drawn to fire. When used correctly they can produce very elegant code; if not for the template programmer, at least for the end user. Yet in all their power, templates in C++ have been lacking a fundamental aspect: a variable number of arguments.

There are ways to work around this limitation, like using a list of types paired with a template-paramlist-object. Sounds familiar? (I know it doesn’t, don’t worry). You could also generate N constructors, one overload for each parameter count. The drawback, exponential compile time (say, TR1). These are all hacks, which are in place only because there wasn’t a safe way of passing a list of types associated with a list of arguments. This is over now with variadic templates in C++0X.

So, what kind of problem would variadic templates solve? Let’s name a few:
* A typesafe varargs function (a function with a variable number of arguments)
* Easily create a template object which acts as a tuple
* An easier implementation of a  reduce (inject) function

This entry is getting quite long so we’ll start seeing these examples on the next post.

CRTP for static dispatching

author Posted by: nico on date Mar 31st, 2011 | filed Filed under: C++, Templates

So, virtual dispatching is just too much overhead for you? I bet you do need every femtosecond from your CPU. Even if you don’t, who doesn’t like weird C++ constructs? Take CRTP, for example, a Curiously recurring template pattern:

  1. template <class Derived> struct CRTP {
  2.     const char* greeting() const {
  3.         const Derived* self = static_cast<const Derived*>(this);
  4.         return self->greeting();
  5.     }
  6. };
  7.  
  8. struct Hello : public CRTP<Hello> {
  9.     const char* greeting() const { return "Hello world"; }
  10. };
  11.  
  12. struct Bye : public CRTP<Bye> {
  13.     const char* greeting() const { return "Bye world"; }
  14. };
  15.  
  16. #include <iostream>
  17. template <class T> void print(const CRTP<T> &amp;x) {
  18.     std::cout << x.greeting() << "\n";
  19. }
  20.  
  21. int main() {
  22.     print(Hello());
  23.     print(Bye());
  24.     return 0;
  25. }

Using this weird looking (ain’t them all?) template device you can have static dispatching with most of the flexibility of dynamic dispatching. As a bonus, you’ll drive all your cow-orkers insane!

Bonus non useful information: In C++ 0X you could use variadic templates and have a proxy object with static dispatching. How cool is that?

Template Metaprogramming XV: Gemini

author Posted by: nico on date Sep 23rd, 2010 | filed Filed under: Meta-post, Templates

This is the end. My only reader, the end. After 15 chapters of template metaprogramming you should have learned why staying away from them is a good idea, but if you have been following this series then you should know now when and why they could be useful.

These posts were a compendium of mostly isolated data I found during my travels through the depths of metaprogramming tricks, there are books and people much more capable than me if you want to learn more about this subject (Modern C++ Design by Andrei Alexandrescu comes to mind).

The whole idea of having a cache and a virtual template method was nice, but after seeing the result I decided it was best to have a factory method and an IDL. It may not be so l33t, but whoever has to maintain the code after me will be grateful.

This is the last post on this topic because I feel I have written most, if not everything, I can transmit through this medium but also for an important reason, most likely I won’t be working with C++ code so much from now on [1] so there won’t be as many chances for me to see the dark, insane, side of this beautiful (in its own way) programming language in a programming language. I know most of you must have barely skimmed through these articles, but I still hope you enjoyed them.

[1] That’s right, I’m leaving C++ for the dark side of development, I’ll be working with Java from now on. Keep in mind this article may have been written a long time before it’s published.

[2] Wow, it was a long time since I used the meta-post category

Template Metaprogramming XIV: Marathon

author Posted by: nico on date Sep 14th, 2010 | filed Filed under: Templates

If you remember previous entry, we got our evil device to the point of getting a specific instance using only a type hint. Now we need to put all the code together. I won’t add much to the code, you should be able to parse it yourself.

  1.  
  2. /***********************************************/
  3. struct NIL {
  4.     typedef NIL head;
  5.     typedef NIL tail;
  6. };
  7.  
  8. template < class H, class T=NIL> struct LST {
  9.     typedef H head;
  10.     typedef T tail;
  11. };
  12. /***********************************************/
  13.  
  14. /***********************************************/
  15. template <class X, class Y> struct Eq { static const bool result = false; };
  16. template <class X> struct Eq<X, X> { static const bool result = true; };
  17. /***********************************************/
  18.  
  19. /***********************************************/
  20. template <class Elm, class LST> struct Position {
  21.     private:
  22.     typedef typename LST::head H;
  23.     typedef typename LST::tail T;
  24.     static const bool found = Eq<H, Elm>::result;
  25.     public:
  26.     static const int result = found? 1 : 1 + Position<Elm, T>::result;
  27. };
  28.  
  29. template <class Elm> struct Position<Elm, NIL> {
  30.     static const int result = 0;
  31. };
  32. /***********************************************/
  33.  
  34.  
  35. /***********************************************/
  36. template <typename LST, int N> struct Nth {
  37.         typedef typename LST::Tail Tail;
  38.         typedef typename Nth<Tail, N-1>::result result;
  39. };
  40.  
  41. template <typename LST> struct Nth<LST, 0> {
  42.         typedef typename LST::head result;
  43. };
  44. /***********************************************/
  45.  
  46.  
  47. /***********************************************/
  48. template <class Lst> struct Instances {
  49.     typedef typename Lst::head Elm;
  50.     Elm instance;
  51.     Instances< typename Lst::tail > next;
  52. };
  53. template <> struct Instances<NIL> {};
  54. /***********************************************/
  55.  
  56. void f(void *x) {}
  57.  
  58. /***********************************************/
  59. template <class TypeLst, int N> struct NthInstance {
  60.     // This one isnt easy…
  61.    
  62.     // This is the next type in the list
  63.     typedef typename TypeLst::tail TypeNext;
  64.     //  * Nth::result is the Nth type in Lst (i.e. char, int, …)
  65.     typedef typename NthInstance< TypeNext, N-1 >::NthInstanceType NthInstanceType;
  66.     //  * typename Nth::result &amp; is a reference to said type and the ret type
  67.     template <class InstancesLst>
  68.     static NthInstanceType& get(InstancesLst &instances_lst) {
  69.         return NthInstance< TypeNext, N-1 >::get(instances_lst.next);
  70.     }
  71. };
  72.  
  73. // Remember we chose a 1-based system (wtf..)
  74. template <class TypeLst> struct NthInstance<TypeLst, 1> {
  75.     typedef typename TypeLst::head NthInstanceType;
  76.  
  77.     template <class InstancesLst>
  78.     static NthInstanceType& get(InstancesLst &instances_lst) {
  79.         return instances_lst.instance;
  80.     }
  81. };
  82. /***********************************************/
  83.  
  84.  
  85. class Facade {
  86.     typedef LST<int, LST<char, LST<float> > > Lst;
  87.     Instances<Lst> instances;
  88.  
  89.     public:
  90.     template <class PK> int find(PK) {
  91.         return Position< PK, Lst >::result;
  92.     }
  93.  
  94.     template <class PK>
  95.     // This is a difficult one… it should be parsed like this:
  96.     //  1) Get the desired instance position using Position< PK, Lst >::result
  97.     //  2) Get the type @ the desired position with NthInstance::Type
  98.     //  3) Define said type as a return type (with an & at the end, i.e. make
  99.     //      it a reference to the return type)
  100.     typename NthInstance< Lst, Position< PK, Lst >::result >::NthInstanceType&
  101.     get_instance(PK) {
  102.         const int idx_position = Position< PK, Lst >::result;
  103.         typedef typename NthInstance< Lst, idx_position >::NthInstanceType IdxType;
  104.         IdxType &idx = NthInstance< Lst, idx_position >::get( instances );
  105.         return idx;
  106.     }
  107. };
  108.  
  109. #include <iostream>
  110.  
  111. int main() {
  112.     Facade f;
  113.     int &a = f.get_instance(1);
  114.     char &b = f.get_instance(‘a’);
  115.     float &c = f.get_instance(1.0);
  116.     a = 42; b = ‘n’; c = 4.2;
  117.     std::cout << f.get_instance(1) << "\n";
  118.     std::cout << f.get_instance(‘a’) << "\n";
  119.     std::cout << f.get_instance(1.0) << "\n";
  120.     a = 43; b = ‘m’; c = 5.2;
  121.     std::cout << f.get_instance(1) << "\n";
  122.     std::cout << f.get_instance(‘a’) << "\n";
  123.     std::cout << f.get_instance(1.0) << "\n";
  124.     return 0;
  125. }
  126.  

The only thing missing now is a map, to convert a primitive type to an index type, but that’s trivial and so it will be left as an exercise for the reader (?). We just implemented the most evil code in the whole world. Next time, the conclusions.

Template Metaprogramming XIII: Heart of Darkness

author Posted by: nico on date Aug 31st, 2010 | filed Filed under: Templates

Last time we had a virtual template dispatch problem… we got to the point of knowing which was the index of the cache we were searching for, now we need to actually retrieve an instance of that cache. That’s a problem. Why? To begin with, there are no instances, only types!

The next logical step would be to create a Map device, to map a list of types to a list of instances… let’s see how can we do that, in pseudocode

  1. instances( H|T ) <- [ create_instance(H), instances(T) ]
  2. instances( NIL ) <- NIL

Looks easy. How can we map that to c++?

  1. template <class Lst> struct Instance {
  2.     typedef typename Lst::head Elm;
  3.     Elm instance;
  4.     Instance< typename Lst::tail > next;
  5. };
  6. template <> struct Instance<NIL> {};
  7.  
  8. #include <iostream>
  9. using std::cout;
  10.  
  11. int main() {
  12.     typedef LST<int, LST<char, LST<float> > > Lst;
  13.     Instance<Lst> lst;
  14.     lst.instance = 1;
  15.     lst.next.instance = ‘a’;
  16.     lst.next.next.instance = 3.1;
  17.     std::cout << lst.next.instance << "\n";
  18.     return 0;
  19. }

All those next.next.next.instance look ugly. Let’s use some more meta-magic to get the Nth instance (why not a [] operator? several reasons, you can’t mix non-const ints with templates nicely, there would be problems to define the return type… all those options are workable but it’s easier if we do this in another device.

  1. template  struct Nth {
  2.         typedef typename LST::tail Tail;
  3.         typedef typename Nth::result result;
  4. };
  5. template  struct Nth {
  6.         typedef typename LST::head result;
  7. };

Remember that one from the toolbox? Now we know how to get a specific index position, yet getting the instance is a different problem (the Nth device returns a type, not an instance). We should do something different, the problem is knowing the return type. What’s the return type for the Nth instance of the Instances list?

  1.  
  2.    type <- Nth(TypesLst, Type)
  3.    type var <- NthInstance(InstancesLst, N)
  4.  

Not so easy, right? This is the translated C++:

  1.  
  2. template <class TypeLst, int N> struct NthInstance {
  3.     // This one isnt easy…
  4.    
  5.     // This is the next type in the list
  6.     typedef typename TypeLst::tail TypeNext;
  7.     //  * Nth::result is the Nth type in Lst (i.e. char, int, …)
  8.     typedef typename NthInstance< TypeNext, N-1 >::NthInstanceType NthInstanceType;
  9.     //  * typename Nth::result &amp; is a reference to said type and the ret type
  10.     template <class InstancesLst>
  11.     static NthInstanceType& get(InstancesLst &instances_lst) {
  12.         return NthInstance< TypeNext, N-1 >::get(instances_lst.next);
  13.     }
  14. };
  15.  
  16. // Remember we chose a 1-based system (wtf..)
  17. template <class TypeLst> struct NthInstance<TypeLst, 1> {
  18.     typedef typename TypeLst::head NthInstanceType;
  19.  
  20.     template <class InstancesLst>
  21.     static NthInstanceType& get(InstancesLst &instances_lst) {
  22.         return instances_lst.instance;
  23.     }
  24. };
  25.  

And the code from fetching the instance itself is even more difficult, so I’ll leave that for next time.

Template Metaprogramming XII: You Really Got a Hold on Me

author Posted by: nico on date Aug 24th, 2010 | filed Filed under: Templates

Remember our virtual template method problem, from the other time? (I know, I said the answer was scheduled for a week after that post, but then I just forgot about it). May be we could avoid the virtual part by keeping a list of all our caches… how would we know which one should we dispatch the message to? Easy, using templates.

Instead of a list let’s keep two, for twice the fun. One for the rows cache, another for the PKs. We can use PK to know which ROW Cache should we choose. Let’s try to write a pseudo code for it:

  1. ROW get_row(PK id) {
  2.     pos <- Position of PK in pks_lst
  3.     return cache[ pos ].get_row( id )
  4. }
  5.  

Doesn’t look too hard. Building on our previous toolbox, let’s use Eq, Position and the definition of a list:

  1. struct NIL {
  2.     typedef NIL head;
  3.     typedef NIL tail;
  4. };
  5.  
  6. template < class H, class T=NIL> struct LST {
  7.     typedef H head;
  8.     typedef T tail;
  9. };
  10.  
  11. template <class X, class Y> struct Eq { static const bool result = false; };
  12. template <class X> struct Eq<X, X> { static const bool result = true; };
  13.  
  14. template <class Elm, class LST> struct Position {
  15.     private:
  16.     typedef typename LST::head H;
  17.     typedef typename LST::tail T;
  18.     static const bool found = Eq<H, Elm>::result;
  19.     public:
  20.     static const int result = found? 1 : 1 + Position<Elm, T>::result;
  21. };
  22.  
  23. template <class Elm> struct Position<Elm, NIL> {
  24.     static const int result = 0;
  25. };
  26.  
  27. class Facade {
  28.     typedef LST<int, LST<char, LST<float> > > Lst;
  29.  
  30.     public:
  31.     template <class PK> int find(PK) {
  32.         return Position< PK, Lst >::result;
  33.     }
  34. };
  35.  
  36. #include <iostream>
  37. using std::cout;
  38.  
  39. int main() {
  40.     Facade f;
  41.     std::cout << f.find(1.0) << "\n";
  42.     return 0;
  43. }
  44.  

Great, now we can find an element on a list of types. The real virtual dispatch for the next entry :D

Template metaprogramming XI: Hidden Agenda

author Posted by: nico on date Jul 20th, 2010 | filed Filed under: C++, Templates
Wow, number eleven already. We’re getting more chapters here than Final Fantasy games. I didn’t even imagine there was so much to write about such an esoteric language features like templates. I do wonder if anyone will actually read it, but that’s a completly different problem.

Enough meta-meta talk: what can we do with all the things we have learned? We can calculate pi and e, we already showed that as an example on one of the first chapters. This chapter I’m going to write about what motivated me to explore the bizarre underworld of template metaprogramming. Some time ago I had to work with a Berkeley DB researching the feasibility of developing a magic cache for (real) DB table. Leaving aside the discussion of whether this is a good idea (the project did have a good reason to be researched) I hit a major roadblock when trying to provide a façde for every table; something like this: See the problem? To do something like that we’d need a virtual template method, and you can’t have that. After seeing that I thought to myself “Hey, I’ll use templates!”. Then I had two problems, but the damage was done, I couldn’t go back. What kind of contorted device could we implement to make such a devious requirement work? I’ll leave you to think it, the answers I came up with next week.

Template metaprogramming X: Zero Minus Ten

author Posted by: nico on date Jun 17th, 2010 | filed Filed under: Templates

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

Translating to pseudo-code:

  1. Position (lst.head, lst) <- 0
  2. Position (e, lst) <- 1 + Position(e, lst.tail)

The translation to C++ is not so trivial this time. Try it, I’ll wait… ready? OK, let’s start

  1. template <class Elm, class Lst> struct Position {
  2.         typedef typename Lst::head Head;
  3.         typedef typename Lst::tail Tail;
  4.         static const bool found = (Head == Elm);
  5.         static const int result = found? 0 : 1 + next;
  6.         static const int next = Position<Elm, Tail>::result;
  7. };

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:

  1. template <typename Elm, typename LST> struct _Position {
  2.         typedef typename LST::head Head;
  3.         typedef typename LST::tail Tail;
  4.  
  5.         static const bool found = Eq<Elm, Head>::result;
  6.         static const int result = (found)? 0 : 1 + _Position<Elm, Tail>::result;
  7. };
  8.  
  9. template <typename Elm, typename LST> struct Position {
  10.         typedef typename Assert<Includes< Elm, LST >::result>::check include;
  11.         static const int result = _Position<Elm, LST>::result;
  12. };

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 > indefinately, causing an error after too many nested template calls. Not nice. We need to add a case to make the compiler stop:

  1. /******************************************************/
  2.  
  3. // Helper: Will fail to compile if the assert is false
  4. class Assertion{};
  5. template <bool cond, class T=Assertion> struct Assert {
  6.         typedef typename T::fail check;
  7. };
  8. template <> struct Assert<true> {
  9.         typedef void check;
  10. };
  11.  
  12. /******************************************************/
  13.  
  14. template <typename Elm, typename LST> struct _Position {
  15.         typedef typename LST::head Head;
  16.         typedef typename LST::tail Tail;
  17.  
  18.         static const bool found = Eq<Elm, Head>::result;
  19.         static const int result = (found)? 0 : 1 + _Position<Elm, Tail>::result;
  20. };
  21.  
  22. // The compiler will try to expand the position check
  23. // after NIL has been reached if this isn’t here
  24. template <typename Elm> struct _Position<Elm, NIL> {
  25.         static const int result = 0;
  26. };
  27.  
  28. template <typename Elm, typename LST> struct Position {
  29.         typedef typename Assert<Includes< Elm, LST >::result>::check include;
  30.         static const int result = _Position<Elm, LST>::result;
  31. };

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 aplicability, trying to use some of all these stuff to implement a real, useful and working program… assuming that’s even posible.

Template metaprogramming IX: Absolute Zero

author Posted by: nico on date Jun 10th, 2010 | filed Filed under: C++, Templates

By now we should have learned how to perform loops, branching and returns using templates. Let’s add a couple of useful operations to our library: append and prepend.

Prepending an element to a list is very easy: the result is a list (oh surprise) consisting of a head (the element we want to add) and a tail (the old list). In the pseudocode I’ve been using so far:

  1. Prepend(e, lst) <- LST(e, lst)

And in C++ (trivial, this time):

  1. template <typename Elm, typename Lst=NIL> struct Preppend {
  2.         typedef LST<Elm, Lst> result;
  3. };

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:

  1. Append(e, NIL) <- LST(e)
  2. Append(e, lst) <- LST(lst.head, Append(e, lst.tail))

Looks complicated what it follows the same structure as the rest of the basic-ops:

  1. template <class Elm, class Lst> struct Append {
  2.         typedef typename Lst::head Head;
  3.         typedef typename Lst::tail Tail;
  4.  
  5.         typedef typename Append<Elm, Tail>::result Next;
  6.         typedef typename LST<Head, Next>::result result;
  7. };
  8.  
  9. template <class Elm> struct Append<Elm, NIL> {
  10.         typedef LST<Elm> result;
  11. };

Easy. Now, what happens if we want to add a default value for Lst, so we can use Append to create lists? Easy too, but we need a façade this time; just rename Append to _Append, then

  1. // This is here just because I wanted a default param :D
  2. template <typename Elm, typename Lst=NIL> struct Append {
  3.         typedef typename _Append<Elm, Lst>::result result;
  4. };

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.

Template metaprogramming VIII: A Rough Whimper of Insanity

author Posted by: nico on date Jun 3rd, 2010 | filed Filed under: C++, Templates

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 tha tail otherwise”. A little bit more formally:

  1. Nth(0, lst) <- lst.head
  2. 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:

  1. template <typename LST, int N> struct Nth {
  2.         typedef typename LST::Tail Tail;
  3.         typedef typename Nth<Tail, N-1>::result result;
  4. };
  5.  
  6. template <typename LST> struct Nth<LST, 0> {
  7.         typedef typename LST::head result;
  8. };

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 recursivly. 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:

  1. Includes(lst.head, lst) <- true
  2. Includes(e, lst) <- Includes(e, lst.tail)

Looks easy, right? Well, there’s a bug there, can you spot it? Yeah, we’re missing the false condition. We should add a third spetialization:

  1. Includes(lst.head, lst) <- true
  2. Includes(e, NIL) <- false
  3. Includes(e, lst) <- Includes(e, lst.tail)

Again, let’s translate the pseudocode to C++. Try it, I’ll wait. Read? OK, this is MY answer:

  1. template <class Elm, class Lst> struct Includes {
  2.         typedef typename LST::head Head;
  3.         typedef typename LST::tail Tail;
  4.  
  5.         static const bool found = (Elm == Head);
  6.         static const bool found_tail = Includes<Elm, Tail>::result;
  7.         static const bool result = found || found_tail;
  8. };
  9.  
  10. template <class Elm> struct Includes <Elm, NIL> {
  11.         static const bool result = false;
  12. };

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 to types. We can use partial template spetialization again:

  1. template <class X, class Y> struct Eq { static const bool result = false; }
  2. template <class X> struct Eq<X, X> { static const bool result = true; }

With this little struct now we can write our include operation this way:

  1. template <class Elm, class Lst> struct Includes {
  2.         static const bool result =
  3.                                 Eq<Elm, typename LST::head>::result
  4.                                  || Includes<Elm, typename LST::tail>::result;
  5. };
  6.  
  7. template <class Elm> struct Includes<Elm, NIL> {
  8.         static const bool result = false;
  9. };

Very esoteric looking, the right mix of Haskel, C++ and booze to ensure job security for life. Next time we’ll find a way to search for the position of an element, a somewhat more complicated task.