Visual Studio 2010 features a number of extensions (activated by default) / discrepancies with regard to the C++ Standard.
Such discrepancies can be surprising, and elicit a different behavior than other behavior. VS is notably famous for being extremely lax in template code validation, and template code that was accepted and compiled by VS will often be rejected outright by more compliant compilers (CLang, Comeau, icc, gcc, ... to name a few).
The goal of this question is to provide a reference (thus the FAQ tag) for these discrepancies.
Please provide one answer per discrepancy (check for duplicate) and for each:
Explain the discrepancy
Tell us if it is possible to disable this (and if so, how)
Explain the consequences (apart from the mere rejection)
Note: C++0x is the next standard, so avoid listing C++0x extensions, since they'll be standard soon
From #Matteo Italia: Visual Studio Compliance Page
First of all, I'd link Microsoft's take on this topic.
All the Microsoft language extensions can be found here; there's also a page where the areas of the language where VC++ is not compliant to the standard are listed.
By default the compiler allows binding a temporary to a non-const reference.
Remedy: use warning level 4
Visual C++ does not fully support value initialization (or rather, there are bugs in all current versions of Visual C++, from Visual C++ 2005 through Visual C++ 2010 SP1).
There are several reported bugs about this (see also this answer to another question).
Consequence: some forms of code that should value initialize an object leave the object or some part of the object uninitialized.
Workaround: do not rely on value initialization.
Discrepancy: Visual Studio does not bind non-dependent names in templates during first evaluation.
The Standard requires two-phases evaluation:
First: check basic templates well-formedness, bind non-dependent names (which comprises overload resolution)
Second: Instantiation proper
Disable ? It is not subject to any option or switch, it is simply not implemented.
Consequences:
Visual Studio only does the second phase, which affects:
Errors in template code are detected at instantiation only, so you'd better instantiate all the templates you write early (think of it as compilation unit test).
Missing template or typename keywords are not detected by VS
Overloads declared after the`template may be picked up by overload resolution. Not so much of an issue since reverting the include order would produce the same result.
I use a blog as a notebook for non-complicance issues I find in VS2005. I don't see a point in reposting the whole thing here
http://atarasevich.blogspot.com/2008/02/microsoft-vs2005-c-non-compliance.html
http://atarasevich.blogspot.com/2008/02/microsoft-vs2005-c-non-compliance_07.html
http://atarasevich.blogspot.com/2008/02/microsoft-vs2005-c-non-compliance_08.html
Related
I am very new to C++ and programming in general and am currently working through Bjarne Stroustrup's Programming: Principles and Practices using C++. I'm consistently receiving the error below
Severity Code Description Project File Line Error C2338 <hash_map> is
deprecated and will be REMOVED. Please use <unordered_map>. You can
define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS to acknowledge that
you have received this warning.
I understand that the header file std_lib_facilities.h using some sort of deprecated function, but is there a way to bypass this? It looks like it wants me to define "_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS" but I'm unsure of how to do that. Any help would be appreciated!!
The warning isn't about "some function" - it's about the whole of stdext. And it's not just hand-wavy, to be discontinued eventually, deprecated: it doesn't ship with 2015.
During the early 00's work was afoot to revise the C++ standard; different compiler vendors, Microsoft included, put proposals before the committee along with prototypes. So they could be tested and evaluated, Microsoft placed implementations of their proposed extensions in stdext.
Eventually the committee chose what they were going to incorporate in that revision and released a Technical Report ("TR1"). Anticipating completion before the end of 2009, this was referred to as "C++0x", and compiler vendors began implementing these features in the tr1 namespace. Finally in 2011 the standard was finalized and we got "C++11" with all its bit and pieces back in std where they belong.
According to Microsoft's proposal, the container would be std::hash_map, but the C++ committee chose to use the term unordered_map. std::map is an ordered container, stdext::hash_map, despite the name, is not.
Microsoft's compiler has been the slowest at getting full C++11 support finished, and the standards committee has since finished a second variation (C++14) and is working on a third (C++17). Microsoft is just-about finishing C++11 in VS2015 and a big chunk of C++14, with a few significant exceptions that are apparently going to be a major problem for the VS compiler (esp constexpr and template variables).
Visual Studio 2015 does not provide stdext - it's gone. This is not one of those "well, it may eventually go away" cases.
stdext is specific to the Microsoft family of compilers, so writing code using stdext:: anything is not portable: http://ideone.com/x8GsKY
The standardized version of the feature you're wanting is std::unordered_map, you should use that. It's essentially the same thing.
There are unresolved bugs in stdext::hash_map.
If you really have to use stdext::hash_map, silence the warning by adding
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
at the top of the stdafx.h I assume your project has, or in your header files before you #include <stdext/...>, or in the solution explorer:
Right click on your project's entry in solution explorer,
Select Properties,
Select Configuration: All Configurations,
Expand the C/C++ tree entry,
Select Preprocessor,
The "Preprocessor Definitions" will probably say <different options>
At the beginning of the "Preprocessor Definitions" entry add _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1; so it reads _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1;<different options>.
(or whatever was there originally should follow the ;)
You can put the define prior to your including of the header generating the warning:
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
#include <hash_map>
You can also add the symbol in Proprocessor Definitions of the project file.
The later looks prettier, but given your doing something against the suggestion of the tool makers, I'd go with the first method, so you don't forget that you might get burnt latter.
It seems that you used old "std_lib_facilities.h" header (stroustrup.com/Programming/std_lib_facilities.h).
New version of this header, working flawless for the "hello,world"-program in MSVS 2015, is available at
stroustrup.com/Programming/PPP2code/std_lib_facilities.h
Found it out when had had the same problem studying PPP.
These pages:
http://www.cplusplus.com/reference/cmath/round/
http://www.cplusplus.com/reference/cmath/rint/
imply that these functions are part of C++11, and Visual Studio 2012 seems to support basically everything in C++11... so where the heck are the rounding functions (not to mention the other additional math functions)?!
I know all about rolling my own rounding function, but it just seems ridiculous at this point. Am I just missing something here and there's some special combination of std:: and tr1:: or another header file to get access to these?
As you say, VS2012 supports "basically everything" from C++11, but that is not the same as "everything".
These functions were added in VS2013 which, for the record, still doesn't support "everything".
When Microsoft initially released Visual Studio 2012 in September 2012, they announced their plan for providing updates for Visual Studio on a more regular basis. Since then, they have released Visual Studio 2012 Update 1 (Visual Studio 2012.1) in November 2012 and Visual Studio 2012 Update 2 (Visual Studio 2012.2) in April 2013.
My question is: Did the updates introduce any changes to the C++ ABI (with regard to the initial VS2012 version)? Is it safe to link .libs of different VS2012 versions?
I have searched the internet for a while and could not find any definite statement from Microsoft. Some sources mention that some bugs in the C++ code generation have been fixed but I suppose that does not imply an ABI change?
Stephan T. Lavavej, a key author of Visual C++'s STL implementation laid out the rules in this Reddit thread:
Here are the precise rules:
If you include any C++ Standard Library headers, you have to play by its rules, and we intentionally break binary compatibility between major versions (but preserve it between hotfixes and service packs). Any representation changes (including but not limited to adding/removing data members) break binary compatibility, which is why this always happens and why we jealously guard this right.
[snip]
So, if you're playing by the STL's rules, you need to ensure the following:
All object files and static libraries linked into a single binary (EXE/DLL) must be compiled with the same major version. We added linker checks, so that mismatching VS 2010+ major versions will trigger hard errors at link time, but if VS 2008 or earlier is involved we can't help you (no time machines). Because the ODR applies here, you really should be using the same toolset (i.e. same service pack level) for all of the object files and static libraries. For example, we fixed a std::string memory leak between VS 2010 RTM and SP1, but if you mix RTM and SP1, the resulting binary may or may not be affected by the leak. (Additionally, you need to be using the same _ITERATOR_DEBUG_LEVEL and release/debug settings; we have linker checks for these now.)
If you have multiple binaries loaded into the same process, and they pass C++ Standard Library objects to each other, those binaries must be built with the same major version and _ITERATOR_DEBUG_LEVEL settings (release/debug should match too, I forget if you can get away with mismatch here). Importantly, we cannot detect violations of this rule, so it's up to you to follow it.
Multiple binaries whose interfaces are purely C or COM (or now WinRT) may internally use different major versions, because those things guarantee binary compatibility. If your interfaces involve the C++ Core Language (e.g. stuff with virtuals) but are extremely careful to never mention any C++ Standard Library types, then you are probably okay - the compiler really tries to avoid breaking binary compatibility.
Note, however, that when multiple binaries loaded into a single process are compiled with different major versions, you'll almost certainly end up with multiple CRTs loaded into your process, which is undesirable.
Bottom line - if you compile everything 100% consistently, you just don't have to worry about any of this stuff. Don't play mixing games if you can possibly avoid it.
Finally, I found an answer to my question in Stephan T. Lavavej's blog post C++11/14 STL Features, Fixes, And Breaking Changes In VS 2013:
The VS Update mechanism is primarily for shipping high-priority bugfixes, not for shipping new features, especially massive rewrites with breaking changes (which are tied to equally massive compiler changes).
Major versions like Visual C++ 2013 give us the freedom to change and break lots of stuff. There's simply no way we can ship this stuff in an Update.
Q5: What about the bugfixes? Can we get those in an Update?
A5: This is an interesting question because the answer depends on my choices (whereas in the previous question, I wouldn't be allowed to ship such a rewrite in an Update even if I wanted to).
Each team gets to choose which bugfixes they take to "shiproom" for consideration to be included in an Update. There are things shiproom won't let us get away with (e.g. binary breaking changes are forbidden outside of major versions), but otherwise we're given latitude to decide things. I personally prioritize bandwidth over latency - that is, I prefer to ship a greater total number of bugfixes in every major version, instead of shipping a lesser total number of bugfixes (over the same period of time) more frequently in multiple Updates.
Some months ago I posted the following question
Problem with templates in VS 6.0
The ensuing discussion and your comments helped me to realize that getting my hands on a new compiler was mandatory - or basically they were the final spark which set me into motion. After one month of company-internal "lobbying" I am finally getting VS 2012 !! (thank you guys)
Several old tools which I have to use were developed with VS 6.0
My concerns are that some of these tools might not work with the new Compiler. This is why I was wondering whether somebody here could point out the major differences between VS 6 and VS 2012 - or at least the ones between VS 6 and VS 2010 - the changes from 2010 to 2012 are well documentes online.
Obviously the differences between VS 6.0 and VS 12 must be enormous ... I am mostly concerned with basic things like casts etc. There is hardly any information about VS 6.0 on the web - and I am somewhat at a loss :(
I think I will have to create new projects with the same classes. In the second step I would overwrite the .h and .cpp files with the ones of the old tools. Thus at least I will be able to open the files via the new compiler. Still some casts or Class definitions might not be supported and I would like to have a general idea of what to look for while debugging :)
The language has evolved significantly since VS 6.0 came out.
VS6.0 is pre-C++98; VS 2012 is C++03, with a few features from
C++11.
Most of the newer language features are upwards compatible;
older code should still work. Still, VC 6.0 is pre-standard,
and the committee was less concerned about breaking existing
code when there was no previous standard (and implementations
did vary). There are several aspects of the language (at least)
which might cause problems.
The first is that VC 6.0 still used the old scoping for
variables defined in a for. Thus, in VC 6.0, things like the following
were legal:
int findIndex( int* array, int size, int target )
{
for ( int i = 0; i < size && array[i] != target ; ++ i ) {
}
return i;
}
This will not compile in VC 2012 (unless there is also a global
variable i, in which case, it will return that, and not the
local one).
IIRC, too, VC 6.0 wasn't very strict in enforcing access
controls and const. This may not be problem when migrating,
however, because VC 2012 still fails to conform to C++98 in some
of the more flagrant cases, at least with the default options.
(You can still bind a temporary to a non-const reference, for
example.)
Another major language change which isn't backwards compatible
is name lookup in templates. Here too, however, even in VC
2012, Microsoft has implemented pre-standanrd name lookup (and
I mean pre-C++98). This is a serious problem if you want to
port your code to other compilers, but it does make migrating
from VC 6.0 to VC 2012 a lot easier.
With regards to the library, I can't remember whether 6.0
supported the C++98 library, or whether it was still
pre-standard (or possibly it supported both). If your code has
things like #include <iostream.h> in it, be prepared for some
differences here: minor for straight forward use of << and
>>; major if you implement some complicated streambuf. And
of course, all of the library was moved from global namespace to
std::.
For the rest: your code obviously won't use any of the features
introduced after VC 6.0 appeared. This won't cause migration
problems (since the older features are still supported), but
you'll doubtlessly want to go back, and gradually upgrade the
code once you've migrated. (You mentionned casts. This is
a good example: C style casts are still legal, with the same
semantics they've always had, but in new code, you'll want to
avoid them, and least when pointers or references are involved.)
Is it possible to get comments on c++11 std methods and classes in VS2012 ? Currently i'm only seeing parameters and return types - and they're a mouthful to interpret for someone learning cpp.
Only if comments are written before the function declaration, which they are not for VS2012 STL implementation, unfortunately (maybe for parsing speed reasons though, maybe not).
Always refer to either the MSDN (type F1 while having the cursor on the name of the function or type), or refer to the standard. I often use http://en.cppreference.com as a reference for everything in the standard.