Explanation of C++ expression on Code::Dive T-Shirts
This year Code::Dive conference was held in Wrocław for the sixth time. It is amazing how all of this has unfolded, especially given the fact that I was involved in it from its very beginning. In recent two years I had too few time and ideas to give talks, but I managed to make small contribution. The task was to prepare some eye-catching slogan or something similar to put on T-Shirts for conference attendants.
C++ roots are common for me and the conference, so I suggested we should put some fancy C++ expression on the T-Shirts:
(+[](){})();
For non-C++ guys it might look like a sequence of random characters, but it is perfectly valid C++ expression. For C++ programmers it isn’t even odd except the plus sign. Lot of attendees were questioning this syntax, but they were coming back saying that “indeed it compiles! What the hell is that?”.
This is what makes it somewhat special - single annoying character that makes you’re not able to explain what’s going on. Frankly speaking this isn’t something I came up with out of blue. I saw it many years ago, it caught my attention and I recalled it when I was thinking about the T-Shirt.
For the sake of this post let’s see how can we decompose the expression to make it much simpler and what the + sign actually does.
In the middle of the expression we have anonymous function, a.k.a lambda. C++ syntax feels like a compromise between readability and expressiveness.
[] () {}
In order to implement anonymous function programmer has to specify three things. This is C++ trivia.
[]
- what variables from the outer scope the function will capture (capture list)()
- function parameters{}
- function body
In our case we’re not capturing any variables, we’re not getting any parameters and we’re doing
nothing, hence it becomes three empty blocks - [](){}
.
Now we know what the core of the expression does. Let us use lambda symbol to denote it and see how it simplifies overall expression:
(+λ)();
We’re left with the plus sign, parentheses and a semicolon - something we shouldn’t even consider.
Let’s explain the plus sign, or unary operator+
to be precise. It isn’t simple without referring
to the standard. Good explanation was given in this SO question.
Generally speaking evaluation of a lambda function depends on whether it captures or not. In our case it doesn’t capture. Let’s see what the standard has to say about that:
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
So when a compiler encounters lambda with empty capture list it will create a class that has that specific conversion operator. In other words there exists a method that converts such a lambda to a pointer to function.
Now let’s see how unary operator+
works:
The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument.
Maybe the wording is unintuitive but it’s all about:
+1 == 1;
+var == var;
+ptr == ptr;
Hopefully now it’s clear :). For the record I was going ever further on making the expression more
cryptic - e.g. ((void)(([](auto)->void{})(+[](){})));
, but… as it is stated in famous Python’s
Zen: Simple is better than complex.
This may come as a surprise to some of you, but C++ is not even close to other languages when it comes to syntax oddities. Please take a look at Malbolge:
(=<`#9]~6ZY32Vx/4Rs+0No-&Jk)"Fh}|Bcy?`=*z]Kw%oG4UUS0/@-ejc(:'8dc