New C++ experimental feature: The tadpole operators


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.

Comments (116)
  1. Joshua says:

    What C++ needs most is operator[]= (lhs version of operator[]).

  2. Eric TF Bat says:

    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

  3. Medinoc says:

    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)

  4. I see what you did there says:

    So the Time Machine has finally been built – amazingly this also works in Visual C++ 6. From 1998!

  5. sergegers says:

    Is it a joke? What about ++ and — operators?

    [The ++ operator modifies its argument. These do not. -Raymond]
  6. abc says:

    Please tell me this is a late April Fools thing.

  7. RRR says:

    Wow!

    So much retard…

    Just wow!

    Wow!

    I just…

    Wow!

    I…

    Wow!

  8. Boris says:

    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?

  9. Medinoc says:

    @Boris: Look at the second part of my message, it explains that ~+y wouldn't work.

  10. Antonio &#39;Grijan&#39; says:

    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?

  11. Antonio &#39;Grijan&#39; says:

    s/Borland 5.5/Borland C++ 5.5/

  12. Russian Reader says:

    This is hilarious. Will translate to my language and share later.

  13. SunChaser says:

    Seems similar to the experimental arrow operator x –> 0

  14. mafu says:

    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.

  15. David says:

    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?

    [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]
  16. SteveP says:

    No thank you.

  17. Optimizer says:

    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.

    [That problem will go away once the optimizer is taught to recognize this operator. Then we could call it the rocket-powered tadpole. -Raymond]
  18. Stephan says:

    Gotta love the party tricks you can come up with when you properly understand your operators.

  19. madbrain says:

    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];

  20. David says:

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

    [While there isn't a -~ 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]
  21. dcon says:

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

  22. Josh says:

    My compliments on your complements.

  23. Brian says:

    Not liking it. Would prefer y++1, z–1,x++5,a–8 where the higher precedence ++ —  are overloaded /repurposed for this 'feature'

  24. Chris says:

    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 :)

  25. ??? says:

    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 :)

  26. Joshua Ganes says:

    You had me intrigued there for a while. Then I thought about how this might affect compatibility for existing code bases…

  27. Steve says:

    Given that tails wiggle I think the tilde should be the tail. It messes up the swimming towards means higher finger string however.

  28. Peter says:

    I think this is a terrible idea.  It's both completely unnecessary and worse worse than the problem it purports to fix.

  29. Sniffnoy says:

    The joke has already been explained in the comments, but people apparently aren't reading them…

  30. David Totzke says:

    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.

  31. Mike says:

    great idea to distract from the compiler lacking all the C++11 features.

  32. Chris says:

    By "all the C++11 features", you mean expression SFINAE, some constexpr, and some C99 preprocessor (and the many bugs we know and love)?

  33. Marc Clifton says:

    Hey Microsoft, which way is FAIL swimming?  Towards you, or away from you?

  34. LeusKapus says:

    This gotta be one of my favorite posts ever.

  35. Wear says:

    It even works if you are compiling from C.

    Man, Microsoft is really going all out on this one.

  36. JM says:

    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.

  37. Byron says:

    This is nearly as fun as the "approaches from above" operator, as in

    x=100;

    while (x –> 0) {

    doSomething(x);

    }

  38. Marco A. says:

    MSVC hasn't shined in C++ standard compatibility, IMHO I'd concentrate more on getting "the old new things" right

  39. Marco A. says:

    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

  40. Mark Y says:

    Joshua: What on earth would []= do??

  41. JJJ says:

    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.

  42. Ruben Bartelink says:

    Will this compose well with tail call optimizations or might they render the result ranine?

    I would also like two second Josh's compliment.

  43. Neil says:

    You're joking, right?  Especially the (x+1) case — you use minus as part of an expression to *add* something to a value???

  44. Andrew says:

    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

  45. Steve says:

    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.

  46. Scott says:

    Give it 5 minutes. This is awesome.

  47. Larry Hosken says:

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

  48. Andy says:

    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.

  49. AndyW2007 says:

    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.

  50. John Doe says:

    Even I am finding it hard to discern sarcasm from honest anguish and disgust in the comments!

    ~-s

  51. scunliffe says:

    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)

  52. Ryan Voots says:

    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

  53. David Crowell says:

    Some people here need to revisit C/C++ operator syntax.  Kudos to Raymond for making me think, then making me laugh.

  54. sharkbait says:

    For extra fun, see what happens when the tadpole is applied to a float.

  55. Craig says:

    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.

  56. A dev says:

    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?

  57. Michael Geary says:

    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 );

       })();

  58. A lisp dev says:

    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?

  59. cheong00 says:

    With parenthesis pair highlighting feature in Visual Studio, I found using parenthesis to spell out precedence cleaner.

  60. Sam Hughes says:

    Excellent post, I have question.  I see these work on y, z, and n.  Will you add support for i, j, and k?

  61. SpiritOfTheThing says:

    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.

  62. wtfdev says:

    This is jargon. C++ needs changes that increase clarity — this just makes it less accessible.

  63. lsl says:

    Perl calls these the "Inchworm-On-A-Stick" operators and they're considered secret (and listed as such in documentation).

    =( )=

  64. madbrain says:

    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));

  65. Nargil says:

    Let's just write our programs in Ogh! It's more readable than this.

  66. Paddy3118 says:

    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.

  67. Henke37 says:

    My favorite is the BangBang operator, for those times when you just need to slam a value into being boolean.

  68. Boris says:

    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?

  69. Joshua says:

    x+~ or x-~ I'd say appear better and is easier to read.

  70. ThomasX says:

    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

  71. Johnson says:

    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?

  72. paysockee says:

    OMG. Looks like the dismissed IE team put hands to C++.

  73. Ex-pertti says:

    WTF, who is mastermind behind this?

  74. Achille says:

    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.

  75. meme says:

    Is this a joke?

    What's wrong with:

    y = ++y % 10;

    ?

  76. melpomene says:

    @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.)

  77. Stephan Leclercq says:

    >> Also doesn't work on my CDC 6600.

    Can some one complement this ?

  78. Neil says:

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

  79. Psyhister says:

    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.

  80. Bartosz Wójcik says:

    It's misleading, especially when the plus one operator uses the minus sign to perform the action.

  81. Justin Olbrantz (Quantam) says:

    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.

  82. Justin Olbrantz (Quantam) says:

    Incidentally, your posting system doesn't work in Firefox.

  83. lilili says:

    These operators are old.

    They work because "~" means "not".

    not 1 = 0xFFFFFFFE = -2,

    -~1 = -(not 1) = -(-2) = 2.

    ~-1 = not -1 = not 0xFFFFFFFF = 0.

  84. Mike Diack says:

    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.

  85. Andy Ash says:

    I like it!

    Now what we need is a "Custard Pie" operator.

    It's like the Tadpole operators but it only allows accretion!

    :D

  86. Rob G says:

    @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?

  87. Jerry Coffin says:

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

  88. Vincent says:

    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!

  89. Dave says:

    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.

  90. McBucket says:

    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?

  91. Ștefan Fulea says:

    …but, but these tadpole operators don't seem to swim well in an unsigned medium!

  92. Goerges d says:

    This tadpole looks more like a spermatozoon. I also think it's a better name because it contains more letters

  93. zzz says:

    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

  94. Joshua says:

    @Rob G: I refer the honorary gentleman to Neil's most excellent explanation.

  95. ConceptJunkie says:

    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!

  96. Marc Brooks says:

    @Stephan Leclercq:

    You win, here's one internet.

  97. Stephan Leclercq says:

    Has anyone mentioned that the Tadpole operators could be written as ??– or -??-

  98. cheong00 says:

    @Nargil: *Double Facepalm*

  99. mi says:

    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

  100. sense says:

    Gotta love you Raymond!

    There I said it :)

  101. hilarious says:

    Based on the comments, clear proof that the 10x programmer existence is true. (or maybe that the 0x programmer exists).

  102. intent-based-programming says:

    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.

  103. Brad says:

    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?

  104. brendan baldwin says:

    "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?

  105. mk says:

    You seem to enjoy demonstrating how many of your readers are fools.

  106. McBucket says:

    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.

  107. mk says:

    "The problem with y = ++y % 10 is that it's not valid C or C++. It has undefined behavior."

    False.

    [C89 6.5.2: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression." C++11 1.9.15: "If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined." -Raymond]
  108. mk says:

    @McBucket

    I don't think you quite understand the full scope of the word "demonstrate".

  109. mk says:

    Me: "False."

    Never mind. (I'm an idiot too.)

  110. Justin Olbrantz (Quantam) says:

    All,

    We need to get this post on Slashdot and watch mayhem ensue.

  111. Simon says:

    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.

  112. TC says:

    y = ++y % 10 is actually valid C++11. See stackoverflow.com/…/14005508

  113. FrankHB says:

    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.

  114. FrankHB says:

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

  115. hagenp says:

    "<strike>PERL</strike> C/C++: indistinguishable from line noise."

Comments are closed.

Skip to main content