How often have you had to write code like this:
x = (y + 1) % 10; x = (y + 1) * (z - 1); x = (wcslen(s) + 1) * sizeof(wchar_t);
Since the +
and -
operators have such low precedence,
you end up having to parenthesize them a lot,
which can lead to heavily nested code that is hard to read.
Visual Studio 2015 RC contains a pair of experimental operators, nicknamed tadpole operators. They let you add and subtract one from an integer value without needing parentheses.
x = -~y % 10; x = -~y * ~-z; x = -~wcslen(s) * sizeof(wchar_t);
They're called tadpole operators because they look like a tadpole swimming toward or away from the value. The tilde is the tadpole's head and the hyphen is the tail.
| Syntax | Meaning | Mnemonic |
|---|---|---|
-~y |
y + 1 |
Tadpole swimming toward a value makes it bigger |
~-y |
y - 1 |
Tadpole swimming away from a value makes it smaller |
To enable the experimental tadpole operators, add this line to the top of your C++ file
#define __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS
For example, here's a simple program that illustrates the tadpole operators.
#define __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS
#include <ios>
#include <iostream>
#include <istream>
int __cdecl main(int, char**)
{
int n = 3;
std::cout << "3 + 1 = " << -~n << std::endl;
std::cout << "(3 - 1) * (3 + 1) " << ~-n * -~n << std::endl;
return 0;
}
Remember that these operators are still experimental.
They are not officially part of C++,
but you can play with them and give your feedback here
learn more about them here.
What C++ needs most is operator[]= (lhs version of operator[]).
Interestingly, research done by the Visual Studio team revealed that a lot of C++ are dyslexic, and/or have awful spelling, so the same experimental operators can also be enabled with the alternate directive #define __ENABEL_EPSPERAMENTLE_TAPDOLE_ORATORS
Call me paranoid, but this looks like an April Fools post that would have been delayed for some reason.
Anyway, the explanation for those who didn't follow: since in 2's complement -y is already equal to ~y + 1, then -~y would be equal to ~~y+1, that is to say, y+1, all with two unary operators, without a need for a compiler support.
(insert Simpsons image macro here)
So the Time Machine has finally been built – amazingly this also works in Visual C++ 6. From 1998!
Please tell me this is a late April Fools thing.
Wow!
So much retard…
Just wow!
Wow!
I just…
Wow!
I…
Wow!
I have to second Medinoc's April Fools' sentiment, especially since Google returns only this post for __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS.
Since I couldn't find the documentation, an obvious question is why not simply ~-y and ~+y?
@Boris: Look at the second part of my message, it explains that ~+y wouldn't work.
Borland seems to be in the game, too. I compiled with Borland 5.5 the following code:
#include <stdio.h>
void main (void) {
printf ("%in", -~3);
printf ("%in", ~-3);
}
And it printed 4 and 2. The amazing thing is that the compiler I used is the command line version from 2000. Maybe the famous time machine is already working and nobody told us?
s/Borland 5.5/Borland C++ 5.5/
This is hilarious. Will translate to my language and share later.
Seems similar to the experimental arrow operator x –> 0
I am so sorry to read about a third of the comments :( Did you not show the downto operator ("–>") recently in this blog, too? All in vain.
I rarely comment on these forums, but this just made me scream…well maybe not verbally, but in my head I am. This is atrocious. Readability is to be admired as well as convenience. I neither find this experimental syntax readable nor convenient nor obvious. Parenthesis do clarify intent, and it is readable, obvious, and not a burden on the compiler or developer. If you have to explain your new operators away in a manner that isn't obvious at first glance, it is likely a bad choice. If this is a c++ proposal, I would veto it. (x+1) and (x-1) aren't too hard to write. It only 'helps' in cases of x+1 or x-1. What about x+2 or x-3? Whoops, still need those parens again. This seems like a solution to a problem nobody thinks exists. Are there people out there actually asking for this syntax? really?
++operator that increments by 2. At least this operator can be stacked:-~-~xis(x+2). -Raymond]No thank you.
Please note tadpoles are slow creatures thus using an tadpole operator can lead to additional processor instructions to be generated by the compiler being when compared to traditional (x+1) operation.
Gotta love the party tricks you can come up with when you properly understand your operators.
Reminds me of the minimum and maximum operators GCC had at some point:
a <? b (minimum)
a >? b (maximum)
a <?= b (clamp a to a maximum of b)
a >?= b (clamp a to a minimum of b)
(they were removed later on)
What I'd really like to see is some kind of implicit loop. Something like:
vec[$i] += vec2[i];
automatically expanding to:
for(size_t i=0; i < vec.size(); i++)
vec[i] += vec2[i];
[By the same logic, we are missing a ++ operator that increments by 2. At least this operator can be stacked: -~-~x is (x+2). -Raymond]
While there isn't a ++ operator that pre-increments by 2, we do have += . Your stacked example is another reason for not supporting this. It doesn't look well and isn't obvious. I would have to count the tadpoles to understand what is being done. I'd hate to see the tadpole syntax behind (x+1000). Granted I am using an absurd and extreme example, it begs the question: Would there be an upper limit to how many times the operator could be stacked? I haven't yet tried on the VS2015RC yet.
-~operator that adds 2, we do have(x+2). So I don't see why the "doesn't generalize beyond 1" argument is so special about-~when it also applies to++. -Raymond]tadpoles are slimy. Guess this operator is very well named.
If this does go beyond experimental, I will FLUNK (with extreme prejudice) any code review I see that contains it. Seriously, "-~" means +1???
(At first I thought there was a typo, "where's the +~?", then I noticed after _very_ close inspection that my dyslexia could kick in full-time.)
My compliments on your complements.
Not liking it. Would prefer y++1, z–1,x++5,a–8 where the higher precedence ++ — are overloaded /repurposed for this 'feature'
vec[$i] += vec2[i]; is already implemented under the name std::valarray. If the positives of valarray outweigh the negatives, that's what it's there for.
Anyway, prefix ++ and — do sometimes scale in C++11 according to the famous "Undefined Behaviour and Sequence Points" post on StackOverflow. ++++a – b is okay. So is ++++a + a. What a crazy world we live in.
On another note, it's good to see a joke convincing enough that people complain about it :)
I wonder if the comments taking this as a serious discussion about experimental features are some sort of meta-level joke (See in particular @David above) :/ Anyhow, it's a cute 2's complement trick :)
You had me intrigued there for a while. Then I thought about how this might affect compatibility for existing code bases…
Given that tails wiggle I think the tilde should be the tail. It messes up the swimming towards means higher finger string however.
I think this is a terrible idea. It's both completely unnecessary and worse worse than the problem it purports to fix.
The joke has already been explained in the comments, but people apparently aren't reading them…
We've had this in C# for ages.
foreach (int number in Enumerable.Range(1,10))
{
Debug.WriteLine(string.Format("Value: {0} Tadpole Value: {1}", number, -~number));
}
You c++ folks need to get with the times.
great idea to distract from the compiler lacking all the C++11 features.
By "all the C++11 features", you mean expression SFINAE, some constexpr, and some C99 preprocessor (and the many bugs we know and love)?
Hey Microsoft, which way is FAIL swimming? Towards you, or away from you?
This gotta be one of my favorite posts ever.
It even works if you are compiling from C.
Man, Microsoft is really going all out on this one.
I've read all the comments and I can't believe nobody's mentioned yet that this isn't guaranteed to work in C. Because, you know, C doesn't guarantee that integers are represented as two's complement. In polite society we're supposed to avoid mentioning this, though, since absolutely nobody likes to deal with ones' complement and sign/magnitude implementations.
I don't know if C++ guarantees two's complement. And I dimly recall that C99 (or C11?) may have actually standardized on two's complement now.
This is nearly as fun as the "approaches from above" operator, as in
x=100;
while (x –> 0) {
doSomething(x);
}
MSVC hasn't shined in C++ standard compatibility, IMHO I'd concentrate more on getting "the old new things" right
This also has the flaw of not supporting tadpoles which disagree on the direction (there is no clear winner as the standard says)
int x = ~-~y % 10; // Where do I go? Omg
Joshua: What on earth would []= do??
I can't believe this post. The tadpole operators have been implemented in gcc for like, forever. But you're making it sound like it's some novel idea? How dare you.
Will this compose well with tail call optimizations or might they render the result ranine?
I would also like two second Josh's compliment.
Is it a joke? What about ++ and -- operators?
++operator modifies its argument. These do not. -Raymond]You're joking, right? Especially the (x+1) case — you use minus as part of an expression to *add* something to a value???
So we are going to replace a well known mathematical notation, used since the 17th century, with an obscure notation which will only be used by C++. Sorry but I think this is a bad idea
This is crazy. Not only because when these tadpoles grow up, your code will literally start JMPing all over the place, but they will also eat all your source flies.
Give it 5 minutes. This is awesome.
> heavily nested code that is hard to read
Has someone, in fact, tried getting "-~x" into some code by claiming that it's more readable? Not sure I trust myself to correctly guess where the line between truth and leg-pulling is in this post; code reviews surprise me sometimes.
This is a terrible idea. These so called 'tadpoles' look nothing like actual tadpoles. They should be called sea snakes.
Also doesn't work on my CDC 6600.
My first question – what is actually wrong with (y+1) in the first place?
I would seriously question that bracketed code is hard to read and would like to see the study that was performed to confirm this. Given that many people who write code have some form of math training from high school and likely have seen operator precedence before.
I would also like to introduce the topic of cognitive loading – I would make the assertion that the tadpole symbolic would increase visual cognitive load (they are not a normal everyday thing, so the reader has to mentally scan for them [which increases cognitive load]. High cognitive load leads to an increased defect count as a side effect of increased complexity. So I would question the value of these features – certainly I would not like them in complex production code.
Even I am finding it hard to discern sarcasm from honest anguish and disgust in the comments!
~-s
I'm all for the new operator… but IMHO the "head" and the "tail" of the tadpole as described above is **Exactly** backwards!
twitter.com/…/602885761264799744 (pic of a tadpole for reference)
Perl has also supported this since 1994 in perl 5. This is just another example of other languages catching up to Perl.
#!/usr/bin/perl
use integer;
print ~-5, "n", -~5, "n";
However with Perl it hasn't been experimental. It's been a built in part of the language for over 20 years now. /s
Some people here need to revisit C/C++ operator syntax. Kudos to Raymond for making me think, then making me laugh.
For extra fun, see what happens when the tadpole is applied to a float.
Seems to work with VC++ 6, too! To enable it, you must use
#define __ENABLE_ESCOTIC_SQUIGGLE_OPERATORS
Looks like the name is still in flux, though.
Why on earth would you make it so easy to mistype "-~" and "~-", and on top of that force people to learn that minus will ADD SOMETHING???? Why not "+~" and "-~" to mean add and subtract?
Because all the major JavaScript engines are written in C++, JavaScript has also inherited the tadpole operators from the underlying C++ implementation. It is still an experimental feature, but you can enable it with the "use tadpole"; directive:
(function() {
"use tadpole";
var n = 3;
console.log( "3 + 1 = ", -~n );
console.log( "(3 – 1) * (3 + 1) ", ~-n * -~n );
})();
Replacing parentheses with tadpoles in C++ because they're considered hard to read??- That's crazy. What's next??- Removing the parentheses between a function's name and its arguments?
With parenthesis pair highlighting feature in Visual Studio, I found using parenthesis to spell out precedence cleaner.
Excellent post, I have question. I see these work on y, z, and n. Will you add support for i, j, and k?
The thing that bothers me is that up till now, if we wanted to tell the compiler "apply the ~ operator, then apply the – operator," we simply wrote -~i. But now we'll have to write -(~i) to make clear that we don't want the new tadpole operator. So we're not really getting away from parentheses. We're just adding them where we formerly didn't need them.
P.S. Raymond, I've been reading your blog almost since the beginning, and this is one of my all-time favorite posts.
This is jargon. C++ needs changes that increase clarity — this just makes it less accessible.
Perl calls these the "Inchworm-On-A-Stick" operators and they're considered secret (and listed as such in documentation).
=( )=
std::valarray doesn't let you do stuff like this:
vec[$i] = table[(vec2[i] & 0xff) + (page << 8)];
printf(vec[$i]);
vec[$i] = state += 0.5f * (vec[i] – state);
vec[$i][$j] = vec2[j][i];
vec[$i] = sinf(i * (2 * 3.14159286f / 256.f));
Let's just write our programs in Ogh! It's more readable than this.
*Ook!, not ogh! (https://esolangs.org/wiki/Ook!)
So to cover a minor need you propose a disruption to the established idea that addition isassociated with the plus and negation with a minus? Instead you think it is reason enough to introduce a new and conflicting idea of tadpoles and direction of swim?
Just because you can do something, you should really learn to self-censure _before_ you publish.
My favorite is the BangBang operator, for those times when you just need to slam a value into being boolean.
In other words, this is really an April pseudo-Fools' post, which only gets away with the tardiness because it's true in fact though not in spirit?
x+~ or x-~ I'd say appear better and is easier to read.
Great. Let's name operators after what they look like. NEVER name operators after what they do. For the sake of consistency please rename the following operators accordingly:
+ the cross operator
– the line operator
* the star operator
/ the slope operator
Well, it seems that the Visual Studio team (or should I say MS policy in general?) reached a point where there is no room for improvement and, instead of releasing a service pack for bug fixes, decided to release another product, adding useless features that nobody will ever use.
Even if you don't admit it publicly, Raymond (it's obvious why), you can't argue the fact that the expression (x+1)%y is MUCH easier and cleaner for humans to read.
P.S.: It is possible to write a program in a single "line" of code. Should we adapt this way of writing code?
OMG. Looks like the dismissed IE team put hands to C++.
WTF, who is mastermind behind this?
Although Python also supports those operators, I'm concerned about F# programmers.
I mean, in F# the "~-" syntax is used to overload the negation operator.
msdn.microsoft.com/…/dd233204%28v=vs.100%29.aspx
It would be a shame if such users were scared off because of these operators.
At least, the ~~~— and —~~~ syntaxes would be more familiar to them…
Fortunately enough, they seem to work too.
Is this a joke?
What's wrong with:
y = ++y % 10;
?
@meme:
The problem with y = ++y % 10 is that it's not valid C or C++. It has undefined behavior.
(Also, yes, this is a joke, and it has been explained in the comments.)
>> Also doesn't work on my CDC 6600.
Can some one complement this ?
@Mark Y: It would provide a convenient way to assign to an element of a class that emulates an array. Contrived example: A class for a variable-length array of pointers to reference-counted elements. Because your storage is raw pointers, you can safely realloc() it, but you have to take care to fix up the refcounts when you store a pointer to the array. Because there's no operator[]=, you have to write an operator[] that returns a reference to a helper type that does the underlying fixup in its assignment operator and has a typecast operator to retrieve the pointer.
I dunno, these "tadpole" operators seem much less readable than parentheses. Shouldn't making code more readable involve getting rid of funky operators that don't speak for themselves?
"Tadpole swimming toward a value makes it bigger", just reading that makes me wanna write some esoteric language that is based on ASCII art, although, I'm pretty sure something like that already exists.
It's misleading, especially when the plus one operator uses the minus sign to perform the action.
Clever girl..!
Somebody has surely said this before me, but I'm not gonna read all those comments: this is basic two's complement math, and an absolutely epic troll.
-x = ~x + 1
~x = -x – 1
So -(~x) = ~(~x) + 1 = x + 1
~(-x) = -(-x) – 1 = x – 1
This will NOT work on old obscure architectures that don't use two's complement math.
Incidentally, your posting system doesn't work in Firefox.
These operators are old.
They work because "~" means "not".
not 1 = 0xFFFFFFFE = -2,
-~1 = -(not 1) = -(-2) = 2.
~-1 = not -1 = not 0xFFFFFFFF = 0.
This has to be some sort of bad joke right? Why on earth do the designers of C++ constantly strive to make the language more terse and ever less human readable? This is just ridiculous.
I like it!
Now what we need is a "Custard Pie" operator.
It's like the Tadpole operators but it only allows accretion!
:D
@Joshua
You are aware, I hope, that ordinary overloads of [] can be used on the lhs, as long as the result is a (non-const) reference?
Very nice. I'm still trying to figure out which is funnier though: the original post, or the comments (the one worrying about backward compatibility was *especially* good).
Such moronic idea just shows the level of C++ team. Instead of graving C++ they play with the corpse, joining red nose and ledigaga's panties. Great job!
I'd really like to see the results of whatever social experiment you are *really* running. This sounds a lot more like something Scott Adams would do.
This is awesome!! I'm adopting this for our company coding guidelines, like, yesterday.
I did note something really curious, though: apparently this operator has the unique property that intervening spaces between the '~' and the '~' (the tad and the pole???) are allowed, such that the expression "-~y" is interprested exactly the same as "- ~ y". Is that intentional? Anyone have some suggestions as to which style is better / more readable?
…but, but these tadpole operators don't seem to swim well in an unsigned medium!
This tadpole looks more like a spermatozoon. I also think it's a better name because it contains more letters
anyway it's the right way to obtain (x+1) on architectures such as risc/mmx/gpu and has been so since the stone age. well actually it's (y==y)+x lol
@Rob G: I refer the honorary gentleman to Neil's most excellent explanation.
Raymond, this is _just_ what we need… more IOCCC fuel… NOT!. Yeah, I checked it out and it looks like you kooks have also added this to C as well. Next thing you know there will be crazy operators like "*++" and "–%" showing up in our beloved language. When will the madness stop?!
Bjarne Stroustrup, call your office!
@Stephan Leclercq:
You win, here's one internet.
Has anyone mentioned that the Tadpole operators could be written as ??– or -??-
@Nargil: *Double Facepalm*
so ridiculous. Can't believe it.
so many things we need in c++ and visual studio and as if they have nothing else to do but add some stupid ideas that nobody needs and are already there like ++ –.
really late april fools.
just go discover internet and read what people complain and miss about in c++ and visual studio …
you have to be dumb or ignore it if you don't do it.
give us options to turn ALL your 'smart' and 'vs will auto do it for you' so we can turn it off or on (like mouse click in VS puts cursor in virtual space even though all virtual space is disabled etc.).
give us decent libraries where we can customize easily and have freedom (unlike mfc, gdi etc)
we want freedom c++ once had
Gotta love you Raymond!
There I said it :)
Based on the comments, clear proof that the 10x programmer existence is true. (or maybe that the 0x programmer exists).
Raymond, did you intend to perform a social experiment here? I always knew that some percentage of posters operated in write-only complain-only mode, but this… this is spectacular proof of just how high that percentage is.
Wow Raymond, this is cruel :). I'm torn between thinking the comments are hilarious and hurting inside a bit for the people who think someone would design this as a language feature (and not an accident of two's complement math). Perhaps you should link to the second post before someone takes things too far?
"The tilde is the tadpole's head and the hyphen is the tail."
The ~ character far better represents a tadpole tail. How do you F that up?
You seem to enjoy demonstrating how many of your readers are fools.
mk: "You seem to enjoy demonstrating how many of your readers are fools."
I think he's allowing them to demonstrate that for themselves.
Brad: "Perhaps you should link to the second post before someone takes things too far?"
There's ample information in the comments right here.
"The problem with y = ++y % 10 is that it's not valid C or C++. It has undefined behavior."
False.
@McBucket
I don't think you quite understand the full scope of the word "demonstrate".
Me: "False."
Never mind. (I'm an idiot too.)
All,
We need to get this post on Slashdot and watch mayhem ensue.
The operator I'd like to see is the long operator->
"i->foo()" is equivalent to "(*i).foo()"
"i–>foo()" is equivalent to "(**i).foo()"
"i—>foo()" is equivalent to "(***i).foo()"
etc.
y = ++y % 10 is actually valid C++11. See stackoverflow.com/…/14005508
Both ISO C and ISO C++ do not guarantee this to work, since 1’s complement and signed magnitude representations for integral types are explicitly allowed.
Since C++11, y = ++y % 10 does not have undefined behavior due to sequence point rules for built-in operators (btw, there is actually nothing normative about "sequence point" in C++11, it is superseded by http://www.open-std.org/…/n2239.html). It is actually y = (y += 1) % 10, and compound assignment in C++11 has stronger guarantee than previous versions. See ISO C++11 5.17, and wg21.cmeerw.net/…/issue637 for details.
Nevertheless, in ISO C it is still undefined because of more than one side effects on the same scalar between sequence points (even if ISO C11 adopted the "sequence before/after" wording).
"<strike>PERL</strike> C/C++: indistinguishable from line noise."