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.
Related
We have a module that pulls in 3rd-party, specifically sqlite_modern_cpp although I don't think that is particularly important. What is important is that code uses C++ feature macros and (specifically) tests for __cpp_lib_uncaught_exceptions to know whether std::uncaught_exceptions is defined.
So far so good, except that we are now looking to change our C++ standard from C++14 to C++17. On iOS builds (don't know fully about other targets) this is suddenly defined. However, we target a minimum version of iOS as 9.3 and, with that, the compiler returns an error to say the minimum value of iOS required is 10.0.
I would prefer, if possible, not to touch the third party code, so my ideal solution to this would be to tell the compiler not to defined __cpp_lib_uncaught_exceptions, so it would fall back to the previous solution. Is there a clean way to do that?
Feature test macros are just normal macros, which you can #undef. Include <exception> first to define the macro, then undef, then include the library. sqlite_modern_cpp is a header only library, so this should cause no problems.
#include <exception>
#undef __cpp_lib_uncaught_exceptions
#include "sqlite_modern_cpp.h"
This is intended to be handled by the availability mechanic in libcxx. For example, __cpp_lib_shared_mutex is controlled by the preprocessor symbol _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex, which is defined according to the minimum declared target versions of the various Apple OSes.
It should be fairly easy to copy this mechanic to similarly define a _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_uncaught_exceptions to disable __cpp_lib_uncaught_exceptions; you would need to patch the headers <version> and <__availability>. You might want to update the Clang issue 39631, which was closed back in 2018 (I believe incorrectly, but maybe the availability mechanic didn't exist back then).
I've been using #include <minmax.h> in my scripts and using min() and max() as expected. I showed this to someone and they had never seen it before, said it wasn't working for them and asked me why I wasn't including <algorithm> and calling std::min() or std::max().
So my question is basically, why aren't I? I found this in a book on C++: "C++ Design Patterns and Derivatives Pricing". Googling "minmax.h", I find a reference to that very book in the top result, so that even more so makes me think it's something abnormal.
Is anyone able to tell me what this is?
The C++ programming language is accompanied by the C++ Standard Library. There is no <minmax.h> header in the C++ Standard Library. No header in the standard-library has the .h extension. Furthermore, the header is not part of the ported C standard library either, as those headers have the c prefix, like <cmath> (which replaces the C standard-library <math.h> header), <ctime>(which replaces the <time.h> header) when used from the C++ Standard Library.
The std::min and std::max functions are declared inside the <algorithm> header.
That being said, there indeed appears to be some MS header called <minmax.h> inside the C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt folder which defines min and max macros, not functions. But, that is some implementation specific header, and you should be using the standard <algorithm> header instead.
why aren't I?
People do all sort of odd things that they heard about somewhere once, be it in school or that came up as some "solution" that fixed their immediate need (usually under timeline pressure). They then keep doing things the same way because they "work". But I'm glad you stopped for a minute to ask. Hopefully we'll steer you back onto the portable C++ route :)
No, there's no need to use the non-standard minmax.h header. On Windows you need to define the NOMINMAX macro before you include any headers whatsoever, and include <algorithm> right after this macro definition. This is just to free the min and max symbols from being taken over by ill-conceived WINAPI macros. In C++, std::min etc. are in the <algorithm> header and that's what you ought to be using. Thus, the following is portable:
#define NOMINMAX
#include <algorithm>
// other includes
#undef NOMINMAX
// your code here
See this answer for details for Windows.
An ancient reference w.r.t. C++, using ancient compilers, supplying examples using non-standard C++ (e.g. headers such as minmax.h)
Note that the book you are mentioning, C++ Design Patterns and Derivatives Pricing (M.S. Joshi), was first released in 2004, with a subsequent second edition released in 2008. As can be seen in the extract below, the examples in the book relied on successful compilation on ancient compiler versions (not so ancient back in 2004, but still far from recent versions).
Appendix D of the book even specifically mentions that the code examples covered by the book may not be standard-compliant, followed by the pragmatic advice that "[...] fixing the problems should not be hard" [emphasis mine]:
The code has been tested under three compilers: MingW 2.95, Borland 5.5, and Visual C++ 6.0. The first two of these are available for free so you should have no trouble finding a compiler that the code works for. In addition, MingW is the Windows port of the GNU compiler, gcc, so the code should work with that compiler too. Visual C++ is not free but is popular in the City and the introductory version is not very expensive. In addition, I have strived to use only ANSI/ISO code so the code should work under any compiler. In any case, it does not use any cutting-edge language features so if it is not compatible with your compiler, fixing the problems should not be hard.
The compiler releases listed above are very old:
Borland 5.5 was released in 2000,
Visual C++ 6.0 was released in 1998,
GCC 2.95 was released in 1999.
Much like any other ancient compiler it is not surprising that these compilers supplied non-standard headers such as minmax.h, particularly as it seems to have been a somewhat common non-standard convention, based on e.g. the following references.
Gnulib Module List - Extra functions based on ANSI C 89: minmax.h, possibly accessible in GCC 2.95,
Known problems in using the Microsoft Visual C++ compiler, version 6.0:
The MS library does not define the min and max algorithms, which should be found in The workaround we use is to define a new header file, say minmax.h, which we include in any file that uses these functions: [...]
What is the worst real-world macros/pre-processor abuse you've ever come across?:
Real-world? MSVC has macros in minmax.h, called max and min, which cause a compiler error every time I intend to use the standard std::numeric_limits::max() function.
Alternative references for the C++ language
Based on the passage above, the book should most likely be considered primarily a reference for its main domain, quant finance, and not such much for C++, other than the latter being a tool used to cover the former.
For references that are focusing on the C++ language and not its application in a particular applied domain (with emphasis on the latter), consider having a look at:
StackOverfow C++ FAQ: The Definitive C++ Book Guide and List.
Say I have the below (very simple) code.
#include <iostream>
int main() {
std::cout << std::stoi("12");
}
This compiles fine on both g++ and clang; however, it fails to compile on MSVC with the following error:
error C2039: 'stoi': is not a member of 'std'
error C3861: 'stoi': identifier not found
I know that std::stoi is part of the <string> header, which presumably the two former compilers include as part of <iostream> and the latter does not. According to the C++ standard [res.on.headers]
A C++ header may include other C++ headers.
Which, to me, basically says that all three compilers are correct.
This issue arose when one of my students submitted work, which the TA marked as not compiling; I of course went and fixed it. However, I would like to prevent future incidents like this. So, is there a way to determine which header files should be included, short of compiling on three different compilers to check every time?
The only way I can think of is to ensure that for every std function call, an appropriate include exists; but if you have existing code which is thousands of lines long, this may be tedious to search through. Is there an easier/better way to ensure cross-compiler compatibility?
Example with the three compilers: https://godbolt.org/z/kJhS6U
Is there an easier/better way to ensure cross-compiler compatibility?
This is always going to be a bit of a chore if you have a huge codebase and haven't been doing this so far, but once you've gone through fixing your includes, you can stick to a simple procedure:
When you write new code that uses a standard feature, like std::stoi, plug that name into Google, go to the cppreference.com article for it, then look at the top to see which header it's defined in.
Then include that, if it's not already included. Job done!
(You could use the standard for this, but that's not as accessible.)
Do not be tempted to sack it all off in favour of cheap, unportable hacks like <bits/stdc++.h>!
tl;dr: documentation
Besides reviewing documentation and doing that manually (painful and time consuming) you can use some tools which can do that for you.
You can use ReSharper in Visual Studio which is capable to organize imports (in fact VS without ReSharper is not very usable). If include is missing it recommends to add it and if it is obsolete line with include is shown in more pale colors.
Or you can use CLion (available for all platforms) which also has this capability (in fact this is the same manufacture JetBrains).
There is also tool called include what you used, but its aim is take advantages of forward declaration, I never used that (personally - my team mate did that for our project).
As used in this answer, I'm looking for a C++11 compatible code for the same but the usage of std::quoted prevents me from achieving that. Can anyone suggest an alternative solution?
I give my answer assuming that you expect to find a generic approach to handle such situations. The main question that defines the guideline for me is:
"How long am I supposed to maintain this code for an older compiler version?"
If I'm certain that it will be migrated to the newer toolset along with the rest of the code base (even though in a few years time, but it will inevitably happen), then I just copy-paste implementation from the standard headers of the next target version of my compiler and put it into namespace std in a separate header within my code base. Even though it's a very rude hack, it ensures that I have exactly the same code version as the one I'll get after migration. As I start using newer (in this case C++14-compatible) compiler, I will just remove my own "quoted.h", and that's it.
Important Caveat: Barry suggested to copy-paste gcc's implementation, and I agree as long as the gcc is your main target compiler. If that's not the case, then I'd take the one from your compiler. I'm making this statement explicitly because I had troubles when I tried to copy gcc's std::nested_exception into my code base and, having switched from Visual Studio 2013 to 2017, noticed several differences. Also, in the case of gcc, pay attention to its license.
If I'm in a situation where I'll have to maintain compatibility with this older compiler for quite a while (for instance, if my product targets multiple compiler version), then it's more preferable first of all to look if there's a similar functionality available in Boost. And there is, in most cases. So check out at Boost website. Even though it states
"Quoted" I/O Manipulators for Strings are not yet accepted into Boost
as public components. Thus the header file is currently located in
you are able to use it from "boost/detail". And, I strongly believe that it's still better than writing your own version (despite the advice from Synxis), even though the latter can be quite simple.
If you're obliged to maintain the old toolset and you cannot use Boost, well...then it's maybe indeed worth thinking of putting your own implementation in.
There are already two compilers that support C++ modules:
Clang: http://clang.llvm.org/docs/Modules.html
MS VS 2015: http://blogs.msdn.com/b/vcblog/archive/2015/12/03/c-modules-in-vs-2015-update-1.aspx
When starting a new project now, what should I pay attention to in order to be able to adopt the modules feature when it is eventually released in my compiler?
Is it possible to use modules and still maintain compatibility with older compilers that do not support it?
There are already two compilers that support C++ modules
clang: http://clang.llvm.org/docs/Modules.html
MS VS 2015: http://blogs.msdn.com/b/vcblog/archive/2015/12/03/c-modules-in-vs-2015-update-1.aspx
The Microsoft approach appears to be the one gaining the most traction, mainly because Microsoft are throwing a lot more resources at their implementation than any of the clang folk currently. See https://llvm.org/bugs/buglist.cgi?list_id=100798&query_format=advanced&component=Modules&product=clang for what I mean, there are some big showstopper bugs in Modules for C++, whereas Modules for C or especially Objective C look much more usable in real world code. Visual Studio's biggest and most important customer, Microsoft, is pushing hard for Modules because it solves a whole ton of internal build scalability problems, and Microsoft's internal code is some of the hardest C++ to compile anywhere in existence so you can't throw any compiler other than MSVC at it (e.g. good luck getting clang or GCC to compile 40k line functions). Therefore the clang build tricks used by Google etc aren't available to Microsoft, and they have a huge pressing need to get it fixed sooner rather than later.
This isn't to say there aren't some serious design flaws with the Microsoft proposal when applied in practice to large real world code bases. However Gaby is of the view you should refactor your code for Modules, and whilst I disagree, I can see where he is coming from.
When starting a new project now, what should I pay attention to in order to be able to adopt the modules feature when it is eventually released in my compiler?
In so far as Microsoft's compiler is currently expected to implement Modules, you ought to make sure your library is usable in all of these forms:
Dynamic library
Static library
Header only library
Something very surprising to many people is that C++ Modules as currently expected to be implemented keeps those distinctions, so now you get a C++ Module variant for all three of the above, with the first most looking like what people expect a C++ Module to be, and the last looking most like a more useful precompiled header. The reason you ought to support those variants is because you can reuse most of the same preprocessor machinery to also support C++ Modules with very little extra work.
A later Visual Studio will allow linking of the module definition file (the .ifc file) as a resource into DLLs. This will finally eliminate the need for the .lib and .dll distinction on MSVC, you just supply a single DLL to the compiler and it all "just works" on module import, no headers or anything else needed. This of course smells a bit like COM, but without most of the benefits of COM.
Is it possible to use modules in a single codebase and still maintain compatibility with older compilers that do not support it?
I'm going to assume you meant the bold text inserted above.
The answer is generally yes with even more preprocessor macro fun. #include <someheader> can turn into an import someheader within the header because the preprocessor still works as usual. You can therefore mark up individual library headers with C++ Modules support along something like these lines:
// someheader.hpp
#if MODULES_ENABLED
# ifndef EXPORTING_MODULE
import someheader; // Bring in the precompiled module from the database
// Do NOT set NEED_DEFINE so this include exits out doing nothing more
# else
// We are at the generating the module stage, so mark up the namespace for export
# define SOMEHEADER_DECL export
# define NEED_DEFINE
# endif
#else
// Modules are not turned on, so declare everything inline as per the old way
# define SOMEHEADER_DECL
# define NEED_DEFINE
#endif
#ifdef NEED_DEFINE
SOMEHEADER_DECL namespace someheader
{
// usual classes and decls here
}
#endif
Now in your main.cpp or whatever, you simply do:
#include "someheader.hpp"
... and if the compiler had /experimental:modules /DMODULES_ENABLED then your application automagically uses the C++ Modules edition of your library. If it doesn't, you get inline inclusion as we've always done.
I reckon these are the minimum possible set of changes to your source code to make your code Modules-ready now. You will note I have said nothing about build systems, this is because I am still debugging the cmake tooling I've written to get all this stuff to "just work" seamlessly and I expect to be debugging it for some months yet. Expect to see it maybe at a C++ conference next year or the year after :)
Is it possible to use modules and still maintain compatibility with older compilers that do not support it?
No, it is not possible. It might be possible using some #ifdef magic like this:
#ifdef CXX17_MODULES
...
#else
#pragma once, #include "..." etc.
#endif
but this means you still need to provide .h support and thus lose all the benefits, plus your codebase looks quite ugly now.
If you do want to follow this approach, the easiest way to detect "CXX17_MODULES" which I just made up is to compile a small test program that uses modules with a build system of your choice, and define a global for everyone to see telling whether the compilation succeeded or not.
When starting a new project now, what should I pay attention to in order to be able to adopt the modules feature when it is eventually released in my compiler?
It depends. If your project is enterprise and gets you food on the plate, I'd wait a few years once it gets released in stables so that it becomes widely adapted. On the other hand, if your project can afford to be bleeding-edge, by all means, use modules.
Basically, it's the same story ast with Python3 and Python2, or less relevantly, PHP7 and PHP5. You need to find a balance between being a good up-to-date programmer and not annoying people on Debian ;-)