I have tried to find some posts or articles but I cant seem to find a good explanation on
What are deprecated enum types,
What deprecated means,
How they are declared, or discovered,
How should they be handled, (or not)
What problems they can cause?
Redirecting me to a helpful article would also be great
Thank you very much!
What are deprecated enum types?
I've never heard that exact wording, but this is essentially an enum (type) marked as deprecated.
What does deprecated mean?
Deprecated means some value, function, or maybe even module is marked as now obsolete or replaced. It still exists for compatibility with older code, but you shouldn't use it in new code anymore unless you really have to. Keep in mind it might be removed in future versions.
How they are declared, or discovered?
I'm not aware of any true standard/cross-platform way to do this, unfortunately. The question linked in the comments has some examples regarding this. If your compiler supports some special markup (#pragma instruction or some kind of attribute), it should issue you a warning or similar, if marked properly.
How should they be handled, (or not)?
As mentioned above, try to avoid stuff marked as deprecated. There's typically some replacement or at least hints on what/how to do it in the future. For example, if you're trying to use some standard library function in MSVC that is marked as deprecated, the compiler will typically tell you which function to use instead.
What problems they can cause?
For now, they most likely won't cause any problem, but you might not be able to utilize all features provided by some library. For example, the classic sprintf() in MSVC never checked the buffer length writing to. If you try using it, you'll get a warning, asking you to use sprintf_s() instead, which will do that security check. You don't have to do so yet (it's marked as deprecated but not removed), but you're essentially missing out. Not to forget that your code might break (and require major rewrites later on), if the deprecated stuff is finally removed.
What are deprecated enum types?
The terminology is ambiguous, but implies some specific enum types have been marked as deprecated using either:
a compiler-specific notation, such that there will be a warning or error if they're used, and/or
documentation without any technical enforcement (whether e.g. a sweeping corporate "coding standard" requiring that say only C++11 enum classes be used, or an API-specific note that specific enum types are deprecated)
What deprecated means?
That the functionality may be removed in a later version of the system, usually because it is considered inferior (whether to some existing alternative, or in terms of maintainability, performance, robustness etc.) or unimportant.
How they are declared, or discovered?
If the deprecation is being enforced by the compiler, then it will be have to be included in the same translation unit as the enum type: it may be in the same header, or in a general "deprecation.h" header etc.. Here's a few examples for a common compiler:
GCC: enum X [ { ... } ] __attribute__ ((deprecated));
for individual enumerations: enum X { E1 __attribute__((deprecated)) [ = value ] [ , ... ] };
How should they be handled, (or not)
When you can, you should investigate why they're deprecated and what the alternatives are, and change the code using them to avoid them.
What problems they can cause?
The immediate problem they cause is that your compiler may generate warnings or errors.
They may well be deprecated because it's not the best idea to use them even with the current software - related functionality may be inefficient, buggy, etc.. For example, given enum Image_Format { GIF, PNG, JPEG, SVG };, GIF may be deprecated in a system because PNG has proven better for the system's users - e.g. perhaps because it supports better colour depth, preserving the colours more accurately, or SVG might be deprecated because some clients have been found to be using web browsers that won't display them, JPEG might be deprecated because it's known the images in the system aren't natural photographic images and the format gives visually poor results despite larger compressed files, slower processing speed and higher memory usage - lots of possible motivations for making things deprecated.
A bigger but not immediate issue is that they could disappear with the next revision of the software "subsystem" providing them, so if you don't migrate old code off them and avoid creating new code using them, your software will have to be fixed before it can work with the update to that subsystem.
Deprecated means -
You can use this feature in the current latest stable release but this feature will be removed in some future release, but which not mentioned.
They are marked by the library or SDK who created them. Some languages use attirubutes to mark deprecated. Like C# uses - [Obsolete] attributes, I am not sure about C++, do don't know what they use to mark deprecated.
They can be removed in any future release. So if you use them, your code or program might not work in future updates, as the feature might have been removed in that future update.
Related
MSVC 16.6 in C++20 mode removes the result_of that was removed in C++20 standard.
I am all for doing the morally correct thing, but many 3rd party libraries(example) I use fail.
Sometimes MSVC enables users to define a define so that removed features are still enabled.
Is there an option to do that for result_of?
I have tried _HAS_FEATURES_REMOVED_IN_CXX20 and it seems to work, but the fact that macro starts with _ scares me, it suggests it may be internal MSVC mechanism and not something users should set.
Defining _HAS_DEPRECATED_RESULT_OF and _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING should more granularly restore result_of and turn off its deprecation warning.
_HAS_FEATURES_REMOVED_IN_CXX20 and _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS should do the same for all C++17 features retired in C++20.
Given past history, these "deprecation overrides" should be relatively safe to use now and for some time coming. Below is an older quote (about VS 2017) from an MS sanctioned blog.
5. (Important!) It’s very likely that you’ll encounter source breaking changes in third-party libraries that you can’t modify (easily or at all). We try to provide escape hatches so you can restore removed features or silence deprecation warnings and get on with your work, but first, please report such issues to the relevant library maintainers. By helping them update their code, you’ll help many more C++ programmers just like you.
P0040R3 (adopted 2016-06, see also N4603) introduced some extended memory management algorithms like std::uninitialized_move_n into the draft, and finally it became parts of ISO C++17. Some of them had an extra overload with a ExecutionPolicy parameter for potential support of parallelism.
However, as of now (Aug 2018), I don't find any standard library implementation shipped with the implementations of these overloads. And the documentation of implementations I've checked does not clarify it well. Specifically, (currently) they are:
libstdc++ shows it does not support P0040R3 in trunk, but actually at least std::destroy_at and std::uninitialized_move_n without ExecutionPolicy are in GCC 8.2.
libc++ has "Complete" support of P0040R3 since 4.0, but the overloads with ExecutionPolicy are actually missing.
Microsoft VC++ has support of P0040R3 since VS 2017 15.3 with /std:c++17 or /std:c++latest, but the overloads with ExecutionPolicy are actually missing.
The only implementation with ExecutionPolicy overloads I know is in HPX, but this is not a full implementation of the standard library. If I want to use the features portably, I have to adapt to custom implementation likewise, rather than direct use of std names. But I still want to use std implementation in future as preference (unless they have known bugs). (The reason is that implementation-defined execution policies are tightly coupled with concrete implementations, so external implementations as well as their client code would likely have less opportunity to utilize various execution policies in general; although this is not necessarily true for client code which is not guaranteed portable in the sense of conforming to standard.) Thus, I want something available for conditional inclusion in my potable adaptive layer for implementations - to get the specified features with using std::... when they are provided by the standard library, and complement it with my implementations as the fallback of missing parts from the standard library implementation only when necessary.
As I have known, the SD-6 feature testing macros as well as P0941R2 shows __cpp_lib_raw_memory_algorithms is sufficient for the features in P0040R3. On the other hand, __cpp_lib_parallel_algorithm seems not related to <memory> at all. So there is no way to express the state like current libc++ and MSVC implementations - with std names from P0040R3 but lack of ExecutionPolicy overloads. And I'm not sure __has_include<execution> would ever work. The reality may be quirkier, e.g. P0336R1 is even not supported by libc++.
So, how to get it perfectly portable in my code when the features become (hopefully) available in some newer version of the standard library implementations, except inspecting the source of each version of them, or totally reinventing my wheels of the whole P0040R3?
Edited:
I know the intended use of feature testing macros and I think libstdc++ has done the right thing. However, there is room to improve. More specifically, my code of the portable layer would play the role of the implementation (like HPX), but more "lightweight" in the sense of not reinventing wheels when they are already provided by the standard library implementation:
namespace my
{
#if ???
//#if __cpp_lib_raw_memory_algorithms
using std::uninitialized_move_n;
// XXX: Is this sufficient???
#else
// ... wheels here ... not expected to be more efficient to std counterparts in general
#endif
}
so my client code can be:
my::uninitialized_move_n(???::par, iter, size, d_iter);
rather than (copied from Barry's answer):
#if __cpp_lib_raw_memory_algorithms
std::uninitialized_move_n(std::execution::par, iter, size, d_iter);
#else
// ???
#endif
Both pieces of the code can work, but obviously checking __cpp_lib_raw_memory_algorithms directly everywhere in client code is more costly.
Ideally I should have some complete up-to-date standard library implementation, but that is not always the case I can guarantee (particularly working with environments where the standard library is installed as parts of system libraries). I need the adaption to ease the clients' work anyway.
The fallback is obvious: avoiding the using std::uninitialized_move_n; path totally. I'm afraid this would be a pessimistic implementation so I want to avoid this approach when possible.
Second update:
Because "perfectly portable" sounds unclear, I have illustrated some code in the edit above. Although the question is not changed and still covered by the title, I will make it more concrete here.
The "perfectly portable" way I want in the question is restricted as, given the code like the edit above, filling up any parts marked in ???, without relying on any particular versions of language implementations (e.g., nothing like macro names depended on implementations should be used for the purpose).
See here and here for the code examples fail to meet the criteria. (Well, these versions are figured out via inspection of commit logs... certainly imperfect, and, still buggy in some cases.) Note this is not related to the overloads with ExecutionPolicy yet, because they are missing in the mentioned standard library implementations, and my next action is depending on the solution of this question. (But the future of the names in std should be clear.)
A perfect (enough) solution can be, for example, adding a new feature testing macro to make the overloads independent from __cpp_lib_raw_memory_algorithms so in future I can just add my implementation of the overloads with ExecutionPolicy when they are not detected by the stand-alone new feature testing macro, without messing up the condition of #if again. But certainly I can't guarantee this way would be feasible; it ultimately depends on the decision of the committee and vendors.
I'm not sure whether there can be other directions.
The initial version of P0941 contained a table which made it clear that P0040R3 has the corresponding feature-test macro __cpp_lib_raw_memory_algorithms. This implies that the correct, portable way to write code to conditionally use this feature is:
#if __cpp_lib_raw_memory_algorithms
std::uninitialized_move_n(std::execution::par, iter, size, d_iter);
#else
// ???
#endif
The imposed requirement is that if that macro is defined, then that function exists and does what the standard prescribes. But that macro not being defined does not really say anything. As you point out, there are parts of P0040R3 that are implemented in libstdc++ - parts, but not all, which is why the feature-test macro is not defined.
There is currently a concerted effort to implement the parallel algorithms in libstdc++.
As to what to do in the #else branch there, well... you're kind of on your own.
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.
Lately as part of my day job I've been learning IBM Rhapsody and using it to generate code in C++ from the UML.
Yesterday it struck me that it might be cool to think about adding state machine support to my C++ compiler, so I jotted a few notes here: http://ellcc.org/wiki/index.php/State_machines_and_Active_Classes
My motivations for doing this are:
It seems like a cool idea.
The compiler could do much better semantic checking (with better error checking) than the current Rhapsody/normal C++ compiler.
There are many optimization possibilities available when the compiler itself understands the state machine structure.
I may try to extend my grammar to except something like the proposal to see how well it works.
What is your opinion of the proposal? Does it seem readable? Does it seem worthwhile?
Edit:
Thanks for the answers recommending specific libraries to do state machines, but that wasn't my question. I've implemented many state machines using both libraries and code that I've written.
I was really looking for ideas, criticism, etc. about the design of a state machine extension to a C++-like language, not whether this change would be appropriate for addition to standard C++. Think of it as a domain specific extension, where my my domain is real-time control applications.
I've started implementation of the extension in my compiler as described here: http://ellcc.org/wiki/index.php/State%5Fmachines%5Fand%5FActive%5FClasses
So far the concept hasn't had to change much going from proposal to implementation but there have been a few changes in details and I'm refining my understanding of the semantics of the problem.
Time will tell whether the whole concept has any value, however. ;-)
With a few exceptions, C++ has traditionally been extended using class libraries, not new keywords. State machines can easily be implemented using such libraries, so I don't think your proposal has much of a chance.
One problem I see in your proposal is the use of 'goto' to go to another state. What happens if I want to use goto in my own code within a state transition?
Excellent work developing what you've done. Something like you've done probably is possible, but I'm doubtful it would ever get into the C++. Most changes that make it into the language itself are included only to allow people to write more useful and powerful libraries.
There's a library here that provides support for state machines. I haven't tried it, but it might interest you, and you may be able to combine your ideas with a library like this to allow other people to make use of it.
http://www.boost.org/doc/libs/1_34_1/libs/statechart/doc/index.html
Or, you could develop your own extension as you suggest, and it would at least be useful for you. Microsoft implement some extension keywords, so there is no reason why you couldn't create your own extended version of C++.
Keep the new ideas coming.
You should take a look at how another smart developer added State machine support to a C-like language: UnrealScript Language Reference. See the section named "States".
UnrealScript supports states at the
language level. In UnrealScript, each
actor in the world is always in one
and only one state. Its state reflects
the action it wants to perform. For
example, moving brushes have several
states like "StandOpenTimed" and
"BumpOpenTimed". Pawns have several
states such as "Dying", "Attacking",
and "Wandering". In UnrealScript, you
can write functions and code which
exist in a particular state. These
functions are only called when the
actor is in that state
It's an interesting idea, but I think you'd actually have better luck creating your own domain-specific language for state machines than officially extending C++. C++ is designed as a very general-purpose programming language. I think Boost has proven that C++ is flexible enough that most features can be implemented nicely using libraries. It also evolves very slowly, to the extent that standard C++ still doesn't even have built-in threading support as of 2009, (it is planned in 0x). So it's unlikely the committee would consider this addition for some time.
Your solution does not look like it has any advantages to a template- or preprocessor-macro-based solution.
I am also not sure, how you can provide better semantic checking. And I doubt that you can apply many useful code optimizations.
However, to allow better optimizations and semantic checking, you should also replace "goto" with a new keyword (e.g. __change__ newState), and disallow goto for state changes! Allow goto for local jumps as usual.
Then the compiler can extract a list of possible transitions.
Read your proposal, have the following comments:
There's actually no keyword to declare and define an actual state machine! Do you assume a single global state machine (and thus a single global state)? How does that relate to __active__ ?
The closest comparable construct in C++ is actually the enum. Why not extend it?
There seems to be some connection between defined events and states, but I fail to see how it's implemented.
Why are threads and timers needed at all? Some use cases of state machines may benefit from them, but a good proposal should keep these seperate. Most importantly this should allow the use of standard C++0x threads.
Personally, I would extend the enum syntax:
enum Foo {
red, blue, green; /* Standard C++ so far - defines states. State list ends with a ; not a , */
Foo() { *this = red; } // Reuse ctor syntax, instead of __initial__
~Foo() { } // reuse dtor syntax, instead of __onexit__
void Bar() {/**/} // Defines an event, no return value. Doesn't need keyword __event__
};
It follows naturally that you can now declare your events in a header, and define them in a .cpp file. I don't even need to suggest the syntax here, any C++ programmer can guess that at this point. Add a bit of inheritance syntax for combined states:
enum DrawingObject : public Shape, public Color { /** } // allows (red && circle)
and you're pretty much at the point where your proposal is, without any new keywords, all by reusing an already familiar syntax.
I have been using ext::hash_map in a C++ project and notice that in g++ 4.3 it is deprecated in favor of unordered_map. I need to maintain compatibility with old systems that do not have unordered_map available. It occurs to me that this is just the sort of thing that could be handled by autoconf, which I am already using. I have been unsuccessful in finding documentation on doing so, however.
I would guess that I need to do something like the following:
- Replace all instances of ext::hash_map in my code with MY_HASH_MAP
- Replace all instances of ext/hash_map in my code with MY_HASH_INCLUDE
- Include a line in configure.ac using some combination of AC_CHECK_HEADERS and AC_DEFINE
I have not been able to figure out exactly the proper autoconf magic to make this work, and am wondering if it is even the best solution anyway. Surely this is the sort of thing that many other people will have dealt with and there might be some standard solution that I have been unable to find?
So, three related questions:
- Is there a standard way of handling this that I should be using?
- How do I do this in autoconf?
- Should I just use -Wno-deprecated and assume the C++ standard is not going to be updated within my lifetime?
You could use AC_CHECK_HEADERS([my_header_file]) to see which files are present -- then create a new class MyApp::hash_map which depending on how what defines are used wraps the functionality accordingly.
I would consider leaving the code as is and turning off the 'deprecated' warning instead, especially if you have to support older systems where you only have ext::hash_map available.
IIRC ext::hash_map is not part of the standard anyway, so the main harm that could be done is that (eventually) the G++ maintainers will remove support for it. However if you rejig the code to include both hash_map and the tr1 unordered_map, you've suddenly doubled the testing effort for this particular bit of code. Unless there is a specific reason that might require you do duplicate the effort, save it for something more worthwhile.