The Visual Studio C++ compiler has this weird nonstandard keyword called __if_
exists
. (And its twin __if_
not_
exists
.) Why does this keyword exist, and how should I use it?
Let’s get this out of the way: Do not use __if_exists under any circumstances whatsoever. This is pretty much a direct quote from Stephan T. Lavavej, maintainer of the Visual C++ implementation of the C++ standard library and overall “person whose opinion on these sorts of matters you should take under serious consideration.” We’ll come back to this topic later in the article.
Okay, so where were we? Right, “What’s the deal with __if_
exists
?”
Set the time machine to 1996.
The world was a much more innocent place. People left their doors unlocked at night and dialed into the Internet over their 28.8 Kb modems to check their AOL account to see if they got mail, hang out in a chat room, check out Yahoo’s top ten sites of the day, and maybe download some software.
Well, that last bit is still true today: Some people still download software over the Internet.¹
This was also an era in which developers counted bytes, so minimizing the size of the download was a big deal. There was this programming language called C++ that hadn’t yet been standardized, but everybody wanted to use it anyway. Compilers of this era didn’t know what vectorization was, they didn’t think to defer code generation to link time, and they didn’t realize that undefined behavior gave them permission to violate the laws of physics.
This was the world that the Active Template Library (ATL) was born into.
The ATL team was obsessed with minimizing code size. They came up with all sorts of ideas for how the compiler could shrink binary sizes. Some of those features turned out to be really good ideas that stood the test of time, like __declspec(novtable)
.
Another of those features was __if_
. It was, in retrospect, not one of those really good ideas.exists
Remember, this was pre-standard C++. Templates existed in rudimentary form. There was no explicit or partial specialization, no traits types, no template meta-programming, and no SFINAE. Templates in this era were not much more than macros on steroids.
The compiler folks were cajoled into creating a prototype for the __if_
feature, and the ATL team was very pleased with how it turned out. The compiler team wasn’t too excited about shipping this prototype-quality feature, but the ATL team insisted that it was essential to making binaries smaller, so the compiler team reluctantly went along with it.exists
And that’s how __if_
ended up in the Visual C++ compiler.exists
Over time, many people got access to high-speed Internet, the C++ language was standardized, template specialization, template partial specialization, and SFINAE were invented, and as a result, template meta-programming became possible. If all of these language features were put into a time machine and sent back to 1996, there would be no need for __if_
.exists
The functionality of the __if_
feature was permanently frozen to what shipped in that first prototype, which was itself just good enough to satisfy the immediate needs of the ATL team. The MSDN documentation was updated to document the specific scenarios that are known to work well, leaving everything else as undefined.exists
And if you go look in the ATL code base, it’s not even used very much. The only places you’ll find it are in the code that was written in that initial release back in 1996. If those classes needed to be rewritten today for some reason, the replacement would certainly not use __if_
.exists
If you have code that uses __if_
, you should consider moving to standards-compliant alternatives. For example, if you’re using exists
__if_
to compile a block of code only if a member function exists (which is what ATL uses it for), you can use SFINAE to do the detection and exists
if constexpr
to conditionalize the compilation.
Thanks to my colleague Jonathan Caves for sharing the history behind __if_exists
(and probably undoing several years of therapy in the process).
Bonus chatter: Jonathan tells me that __if_exists
is a gift that keeps on giving. Whenever the Visual C++ team goes in and rewrites their C++ parser to handle new language features, or simply to make it run better, they have to retrofit __if_exists
support into it. And that’s when they discover some of the truly insane things people have done with it, like putting code inside an __if_exists
block that do not even form a complete C++ construct. The gift has even spread to other compilers: clang 3.0 added support for __if_exists
. So now multiple compiler vendors have therapy bills to pay.
¹ Okay, and some people still access the Internet over dial-up.
It seems that we’ve entered “What Microsoft has done to reduce product size in the past” week.
Any story to share on things like, “self extracting EXE” like the one used in Norton Utilities or so?
surely using the preprocessor to make code conditional would have been better than the __if_exists and
__if_
not_
exists
keywordsThis doesn’t work:
Today, we would use SFINAE to invoke the
VerifyAccess
method if it exists. In 1996, no such luck.I wanted to be sure I understood what __if_exists does and found docs that say:
"The __if_exists statement tests whether the specified identifier exists. If the identifier exists, the specified statement block is executed."
Surely they mean "compiled", not "executed", right? This is a compile-time mechanism. While the code block will be executed as well, you point out in your article here:
"And that’s when they discover some of the truly insane things people have...