Please read the edit below. This case has a very subtly trap.
------
Old comment:
Makes sense it's undefined behavior, because address 0 is involved. Although I'd guess compiler implementations might just drop whole statement, because length is 0.
Zero length memory copy is a no-op.
Just like static zero iteration loop. They become zero instructions. (Except of course initialization that affects something outside loop scope.)
Edit:
Changed my mind after learning about the tricky UB pathway: If compiler can statically prove memcpy length argument to be zero, it can ALSO prove both argument pointers to be not NULL!
Well, just before I just saw a "read" and a "write" to address 0.
Not as mechanism that can cause serious bugs, when the compiler can statically prove length argument to be 0 and you can have NULL arguments as input.
Calls to memcpy with zero length are definitely not uncommon. Macros are an obvious way, but it's worse. All you need is a data flow where compiler can statically prove that all paths lead to zero length argument.
I have to agree it's very scary that memcpy(NULL, NULL, 0) is undefined.
It really should be a no-op. The C and C++ standards are seriously broken in this respect, and compiler authors take advantage of this brokenness to get away with miscompiling programs that, to anyone with common sense, are fine.
The C and C++ standards must be changed to explicitly state that memory operations on zero bytes do nothing regardless of whether the inputs are valid pointers.
Ouch. Didn't think about that compilers can then assume passed pointers aren't NULL. And proceed to optimize your NULL checks away, because that memcpy would have been undefined behavior.
It seems so obvious after reading that. Should always ask oneself "what can the compiler prove as a consequence of this undefined behavior?".
So, you're right, memcpy(NULL, NULL, 0) should be defined as a no-op.
Well, undefined behavior is generally a good thing. It enables a lot of very reasonable optimizations.
Zero-length memcpy pathway to UB is not obvious, because whether the whole thing is UB depends on whether compiler can statically prove the length to be zero. Ugh.
I think the statically-prove-length-is-zero thing is a distraction. What do you think of memcpy(ptr1, ptr2, 1)? The compiler should be able to assume (legitimately, this time) that ptr1 and ptr2 are non-null. The problem isn't a special case for zero length: the problem is the lack of a special case for zero length.
Undefined behavior does not enable optimizations. Rather, the compiler may conclude that something must be true, because the alternative would be undefined behavior. Then, it may make optimization decisions based on that thing being true, causing potentially mysterious errors if, in fact, that thing is not true because the programmer made a mistake.
It's also possible you're confusing undefined behavior with implementation defined behavior.
memcpy behavior is not part of C++ standard. The C++ standard is only concerned with formally defining the ability to use it and the header name to include.
but memcpy outside the C++ scope is what I meant. The C++ committee cannot do much about memcpy but they can introduce a new memcpy with a different name that has better ub support.
The C++ committee can and does change how functions of the C standard library work in C++, see Appendix C of the C++ Standard (granted, most of those changes simply specify how the library functions interact with C++ features).
But the C++ standard could, without any changes to C, be amended to formally define which assumptions the compiler may or may not make about the C API in certain edge cases, such as memcpy(0,0,0).
memcpy is outside the territory of C++. it doesn't fall under the language specification. it's as simple as that. If they go this route what stops them from defining assumptions to system calls?
It will be great to see variants as a standard part of the language. Variants provide a way of doing a sort of type safe union for different types of data.
The new variant feature is based on boost::variant, which you can use today. Getting the thing into the standard library is nice and all, but it doesn't open up new capabilities the way that new syntax does.
The implementation of variant in C++17 is very different than in Boost. The Boost variant has a double buffer for the entire variant, and one of these buffers is always kept on the heap even if your variant is on the stack! This acts as a safety net incase the changing of the variant's value were to throw, you can get the old value back.
This implementation did not fly for C++'s goal of being high performance, and thus the new standardized variant is done quite differently.
I did not have a good experience with boost::variant ... Compile times increased drastically, compiler error messages became enormous and garbled with templates, syntax was onerous in places (e.g. "make_recursive_variant"), and identification of types is based on arbitrary index value that is risky to rely on (which() method). I ended up refactoring the whole thing, removing boost::variant and just using the traditional visitor pattern. The only advantage boost::variant really has over traditional C++ visitor pattern is that boost static_visitor functions can have a non-void return type ... Being able to directly return a value in the visitor functions is admittedly very convenient, but the other issues negate this convenience.
The boost implementation is certainly showing its age at this point, as is mpl, now we have variadic templates.
Are there any C++14 variant implementations compatible with boost::variant and std::variant which are based on variadic templates? I'd love to move to a more modern implementation if possible.
My understanding is it is partly an enabling step to later introduce some sort of pattern matching along the lines of the work Bjarne had been doing so new syntax will likely come.
> but it doesn't open up new capabilities the way that new syntax does
Taking very normal so-what code and moving it into the standard is pretty much the point. Having variant in std:: lets new code use variants without adding a boost dependency. I say that without knocking on boost. Fewer dependencies are always better.
constexpr if seems pretty neat, previously you could do things like constexpr bool foo = /* some constexpr */, this makes it a bit easier and saves a line.
Structured bindings seem like one of those things that was just forgotten in previous standards, I'm glad it's here now. The syntax is a matter of taste, I guess.
I'm also quite excited about variants, they probably won't be used much but sometimes they're just what one needs. Having them without requiring boost is nice.
I think it's only consistent. Static assertions should always always always hold (things like type checks etc), if you really want to only evaluate it in that branch you can still do
Hmm, it seems this constexpr if is much more limited than I realized then. If I understood correctly the code in the the body of the constexpr if has to be correct even if the condition does not hold. I.e., this code:
will not work if you pass in a type for x that does not have a member function f. Is my understanding right? If so, constexpr if is not nearly as nice as I thought...
In my reading of it, this code would work. The code in if constexpr must be well-formed but does not have to be semantically valid. Your code is well-formed but not semantically valid, so this would be the perfect use for if constexpr
You may be correct, and I certainly hope you are. But if that's the case then the static_assert behavior seems all the more puzzling.
In particular if this code works, then you can roll your own "static_assert" that will not trigger from the not taken branches.
Since the intended use of constexpr if is to block template instantiations, static_assert is kind of orthogonal to that. static_asserts in non-instantiated templates are ignored, as you would expect.
You are saying that static_assert would not trigger here, correct? That makes sense to me, but it's not what is in the proposal [1] - see the "Not proposed" section.
P.S: It might compile with Microsoft's Visual Studio, but only because that compiler doesn't implement two-phase name lookup, effectively turning every name into a dependent name.
Oh tricky! I did write that code on my phone so hopefully you'll excuse the sloppiness. Thanks to HN I have miraculously learned a new thing about C++ when I was sure I knew it all; though, not surprised.
Also this dependent name behavior of static_assert seems to be a precedent for always checking static_assert in constexpr if.
I'm very disappointed the networking ts wasn't included (I must have missed when that stopped being a C++ 17 thing). It's one of the few things missing that would let me use C++ for more projects (yes I know I can just include the boost library since that's essentially what it'll be but that's not always the easiest thing to grab and build into an existing project (at least not for a C++ novice like myself) but being part of the standard will make it immensely more accessible).
I'm not sure that you should be writing network code in C++ (which is a notorious source of nasty security bugs) if you're not comfortable enough with C++ to link against one of its most popular freely-available libraries.
I'd rather the committee focus on longstanding language core issues than add everyone's favorite library.
I had to write a plug in that makes a REST call a couple of weeks ago. This thing was ~200 LOC max and I had to link to a library that is orders of magnitude larger just to make an HTTP call. I would have loved some standard networking functionality in that instance.
The point was that you have to pull in third party library; LOC has nothing to do with it. I know all about libcurl. I work on an FDA regulated product; do you know what it takes for me to get third party code into our system?
Meh, I used to use C++ about 10 years ago and very much enjoyed it but the lack of multiple, built-in and cross-platform ways of doing things, like networking that higher level languages had I just simply stopped using it. This would give me an excuse to check it out again because, being part of the STL, it would be trivial to include in a project.
If I have a reason to use the language I can learn the build tooling (which last time I used C++ they were very, very old and overly complex IMO; nothing easy like rust's).
If you want to drive adoption of C++ you need to lower friction to using it. This works in every single thing ever created. If you can get more features into the STL that the vast, vast majority of languages have built in and get good tooling you'll have a very easy way for someone to jump into the language.
Alternatively you can continue to keep the friction high and address "language core issues" instead of making the STL have parity with all other popular languages. I think that approach is terrible but only if your goal is to grow the community of developers. But that's just my opinion of someone who loved C++ 10 years ago but had to move to higher level languages just to get stuff done, quickly and efficiently.
Networking TS is pretty much based on the Boost Asio library. In fact, there is a non-boost standalone Asio library http://think-async.com/Asio/AsioStandalone that has no dependencies on boost and can just be used as a header-only library.
Using sockets is very portable imo. If I remember correctly there's only 2 functions that differ between linux and windows[1]. I'd rather use 2 source files than the whole boost asio/networking library.
[1] Those are ioctlsocket vs ioctl, and closesocket vs close.
A basic TCP implementation can be cross platform with as little as 2 #ifdef/#endif blocks.
I'm a bit frightened with the move toward adding a compile-time sublanguage. Frightened because I feel it will end up being half-baked and then abandoned like other C++ features (virtual inheritance for example).
As an example, I've been exploring Sean Parent's idea of concept-based polymorphism that allows you to implement "virtual functions" that get bound at compile time. To make this scheme explicit, I need to assert in the base class that all my "derived" classes implement a method with a certain signature. Does C++ allow me to do this?
The C++ template system is already a Turing-complete functional programming language and has been since C++'s inception. I see nothing wrong with making this language's syntax more convenient.
> half-baked and then abandoned like other C++ features (virtual inheritance for example)
Virtual inheritance has its place. It's part of the language and works fine. What would you change?
Virtual inheritance means you have a diamond pattern and haven't separated your components properly. It should have never made it into the language as far as I'm concerned.
> Virtual inheritance means you have a diamond pattern and haven't separated your components properly.
I've seen this argument pop out time and again as if it was a mantra of sorts, and more often than not it comes from someone with a background almost exclusively founded on Java.
Their line of reasoning essentially boils down to "Java doesn't support it, the people behind Java said something about it, therefore it's bad".
But C++ isn't Java, nor does Java dictate what is correct or what makes sense.
Particularly when the only assertion you could come up with to criticize multiple inheritance was a comment that had nothing to do with C++ or even OO programming, but only to do with your personal taste regarding your superficial impressions regarding software design.
Ooo, that Java remark burns. I've only touched Java seriously in the last few years of my career, I'm a hardcore C++/native type.
Here's the issues I take with virtual inheritance:
1. It complicates the vtable and function/member calls leading to another level of indirection, so from a performance perspective it's a negative mark.
2. The more fundamental problem is that you've botched the hasA vs isA association. If you have two classes that share a base class then that base class should be refactored into a component that can then be used as a member without polluting the class hierarchy. This leads to better composability since you can now pass this object around without pulling a whole class hierarchy with it.
You're welcome to use virtual inheritance all you want in your projects but much like knowing what subset of C++ to use(and what not) you'll never see it in code I work on.
In many senses, C++ inheritance is just shorthand for composition. That's why things like private inheritance are useful. Through this lens, virtual inheritance is automatic composition in which multiple composed objects each have a pointer to some shared object (the virtual base). It doesn't mess with hasA vs. isA at all.
> knowing what subset of C++ to use
This idea that a good coding standard necessarily bans parts of C++ has done massive damage to the C++ community. The correct subset of C++ to use is C++. Turning off parts of the language is just a cheap way to look sagacious while infantilizing developers. Every feature has its place.
I think we're just going to have to agree to disagree here.
There's a been a fair number of projects I've worked on where exceptions and RTTI introduced too much memory/perf overhead so we explicitly didn't use them. I don't feel like we were worse off for not having them.
I prefer not to work on projects that ban exceptions and RTTI. These features (especially exceptions) are important parts of the language, and without them, you can't reliably use most of the standard library (see bad_alloc) and can't really deliver value semantics, since you need awful hacks like two-phase initialization to communicate failure.
C++-without-exceptions is a very different and much worse language.
> If you're interested in limiting your market, there's a whole embedded and high performance space where this is critical.
Well, it's a preference, not a hard requirement. I'll hold my nose and work on such a codebase if there are other reasons, like the project itself being very interesting.
> Considering LLVM takes the same stance
IMHO, that's a mistake. But LLVM is an example of a project that's compelling enough to work on despite what I consider a set of poor language choices.
Nice! Now to make the idea of compile time virtual functions real, can you force derived classes to have foo_impl, and have an inlined function foo in the base class that calls foo_impl?
What about grand children classes?
When the derived class doesn't have any method "foo_impl" (or no "foo_impl" with a suitable signature), you will get a compile-time error.
No need for the static_assert, that was just because KKKKkkkk1 asked whether checking for the existence of a method at compile-time was possible.
Compile-time polymorphism is essentially duck typing: If it quacks like a duck you can treat it as one. If it doesn't quack like a duck, but you still treat it as one you get a compiler error.
"To make this scheme explicit, I need to assert in the base class that all my "derived" classes implement a method with a certain signature. Does C++ allow me to do this?"
As the call is resolved at compile time, simply calling the function will cause a compile error if the derived class doesn't implement it. The error message might not be the prettiest, but there are ways to improve that.
I'm always happier the more I see old cruft removed in a new C++ standard.
Trigraphs [1] are gone. Good riddance, they're just used for pointless pranks anyways. Otherwise they just seem to cause issues, there's always someone who didn't know about them at all.
Also "unexpected_ownership_move" err... "auto_ptr" is gone [2]. Yeah, I know, there's nothing inherently wrong with it and you knew how to use it correctly...
Removing these facilities is a stunt. Real compilers will have to support them for decades (maybe at least auto_ptr) anyway, so there's no sense deleting them from the standard. It's sufficient to just recommend against their use.
I wouldn't say it's just a stunt. While they will remain supported, their removal from the standard can be cited by engineers for political support to modernize code bases. Compilers also support strict compilation modes which remove obsolete functions, to help modernize your code base. This is all facilitated by removal from the standard.
>While they will remain supported, their removal from the standard can be cited by engineers for political support to modernize code bases
Man... Who do you work for? If I used that as a reason for a refactoring my boss would laugh at me (and he's technical) . I imagine his boss would glaze over for a bit and then ask him to leave his office.
I think this casts my explanation in a very ungenerous light, I'm not really such an absurd person. Think of how a reasonable engineer would do it.
Speaking as an engineer, some of us have a tendency to want to refactor and polish code past the point where we should ship it and move on to something else. Management also has a tendency to view refactoring as unproductive and hurtful to the company's bottom line. Both are very reasonable positions. In most cases, the best strategy tends to be in the middle somewhere.
The auto_ptr class is gone from C++17 because it is error-prone to use it and there are better alternatives. However, I don't need to explain the intricacies of auto_ptr to my boss. I can just say something like, "We want to keep up with the latest industry best practices and standards. Some simple changes to our code base will reduce the chance for bugs and reduce support costs, and make it easier to develop new features."
The fact that auto_ptr has been removed from the standard entirely sends a stronger signal that you really should stop using it. Which is a good signal to send.
Trigraphs are actually incredibly annoying, because they silently change the meaning of characters (including in string literals). This is especially a problem when you use code generators.
It's why most C++ compilers these days don't even enable them by default. Kicking them out of the Standard is merely the recognition of that practice.
Thanks for a terrifying read! I shudder to think what sort of (now essentially solved) problems the engineers on those teams must have to deal with. I mean, if their code page doesn't even support [, {, }, or ], then imagine what must happen when someone tries to enter a non-english name into their system!
It's remarkable that such systems still exist (and are apparently being updated, without their foundational cracks fixed) still today!
And it's patently absurd to consider their argument that 1) they're still using trigraphs, but 2) intend to build against the C++17 spec.
FFS, if you somehow find both of these to be true, preprocess your source to convert trigraphs to the corresponding glyphs, and to a character encoding that supports them. I can't possibly believe that they're running a C++17 compiler on a system that has no support for such a character set.
Modules didn't make it in but are arguably top of the list of practical improvements for everyone and considering the time it will take to trickle down to toolchains and build scripts.
"The braces are needed, getvalues returns a tuple. std::pair is not mentioned in the proposal, so its unclear if this works with pair, which is returned by the STL in some insert methods."
Destructured bindings will work with arrays; plain aggregate structs; and any class that offers a specialization of std::get<>(), so both std::tuple and std::pair are supported as a consequence. (C++11 added std::get<>() for std::pair).
Otherwise, if the expression std::tuple_size<E>::value is a well-formed integral constant expression, the number of elements in the identifier-list shall be equal to the value of that expression
(E is the return type of "getvalues" in squidbidness's example, the initializer-list is "a, b, c".)
103 comments
[ 3.7 ms ] story [ 175 ms ] thread------ Old comment:
Makes sense it's undefined behavior, because address 0 is involved. Although I'd guess compiler implementations might just drop whole statement, because length is 0.
Zero length memory copy is a no-op.
Just like static zero iteration loop. They become zero instructions. (Except of course initialization that affects something outside loop scope.)
Edit:
Changed my mind after learning about the tricky UB pathway: If compiler can statically prove memcpy length argument to be zero, it can ALSO prove both argument pointers to be not NULL!
Ouch!
Why handle 0x0 differently?
Not as mechanism that can cause serious bugs, when the compiler can statically prove length argument to be 0 and you can have NULL arguments as input.
Calls to memcpy with zero length are definitely not uncommon. Macros are an obvious way, but it's worse. All you need is a data flow where compiler can statically prove that all paths lead to zero length argument.
I have to agree it's very scary that memcpy(NULL, NULL, 0) is undefined.
Sure about that?
It really should be a no-op. The C and C++ standards are seriously broken in this respect, and compiler authors take advantage of this brokenness to get away with miscompiling programs that, to anyone with common sense, are fine.
The C and C++ standards must be changed to explicitly state that memory operations on zero bytes do nothing regardless of whether the inputs are valid pointers.
It seems so obvious after reading that. Should always ask oneself "what can the compiler prove as a consequence of this undefined behavior?".
So, you're right, memcpy(NULL, NULL, 0) should be defined as a no-op.
Zero-length memcpy pathway to UB is not obvious, because whether the whole thing is UB depends on whether compiler can statically prove the length to be zero. Ugh.
It's also possible you're confusing undefined behavior with implementation defined behavior.
It's used everywhere in real life C++ code.
quotemstr got a very good point and I'm grateful for the heads up.
C++ is not 100% compatible with C.
This implementation did not fly for C++'s goal of being high performance, and thus the new standardized variant is done quite differently.
The interface is very similar, but the implementation is ofc using C++17 and not C++03.
Are there any C++14 variant implementations compatible with boost::variant and std::variant which are based on variadic templates? I'd love to move to a more modern implementation if possible.
Taking very normal so-what code and moving it into the standard is pretty much the point. Having variant in std:: lets new code use variants without adding a boost dependency. I say that without knocking on boost. Fewer dependencies are always better.
Structured bindings seem like one of those things that was just forgotten in previous standards, I'm glad it's here now. The syntax is a matter of taste, I guess.
I'm also quite excited about variants, they probably won't be used much but sometimes they're just what one needs. Having them without requiring boost is nice.
You can still do this sort of stuff with template overloads, but it's much more cumbersome.
[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p029...
(Of course since this is a full specialization, there are no dependent names.)
See C++14 Standard §14.6.2 (Dependent Names) or http://en.cppreference.com/w/cpp/language/dependent_name (not sure how accurate that page is, though).
P.S: It might compile with Microsoft's Visual Studio, but only because that compiler doesn't implement two-phase name lookup, effectively turning every name into a dependent name.
Also this dependent name behavior of static_assert seems to be a precedent for always checking static_assert in constexpr if.
At least it still exists much like some of the other ones like the filesystem ts. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n458...
I'd rather the committee focus on longstanding language core issues than add everyone's favorite library.
Libraries are fine, but the problem here might be about OS or platform.
If I have a reason to use the language I can learn the build tooling (which last time I used C++ they were very, very old and overly complex IMO; nothing easy like rust's).
If you want to drive adoption of C++ you need to lower friction to using it. This works in every single thing ever created. If you can get more features into the STL that the vast, vast majority of languages have built in and get good tooling you'll have a very easy way for someone to jump into the language.
Alternatively you can continue to keep the friction high and address "language core issues" instead of making the STL have parity with all other popular languages. I think that approach is terrible but only if your goal is to grow the community of developers. But that's just my opinion of someone who loved C++ 10 years ago but had to move to higher level languages just to get stuff done, quickly and efficiently.
[1] Those are ioctlsocket vs ioctl, and closesocket vs close. A basic TCP implementation can be cross platform with as little as 2 #ifdef/#endif blocks.
As an example, I've been exploring Sean Parent's idea of concept-based polymorphism that allows you to implement "virtual functions" that get bound at compile time. To make this scheme explicit, I need to assert in the base class that all my "derived" classes implement a method with a certain signature. Does C++ allow me to do this?
The C++ template system is already a Turing-complete functional programming language and has been since C++'s inception. I see nothing wrong with making this language's syntax more convenient.
> half-baked and then abandoned like other C++ features (virtual inheritance for example)
Virtual inheritance has its place. It's part of the language and works fine. What would you change?
I've seen this argument pop out time and again as if it was a mantra of sorts, and more often than not it comes from someone with a background almost exclusively founded on Java.
Their line of reasoning essentially boils down to "Java doesn't support it, the people behind Java said something about it, therefore it's bad".
But C++ isn't Java, nor does Java dictate what is correct or what makes sense.
Particularly when the only assertion you could come up with to criticize multiple inheritance was a comment that had nothing to do with C++ or even OO programming, but only to do with your personal taste regarding your superficial impressions regarding software design.
Here's the issues I take with virtual inheritance:
1. It complicates the vtable and function/member calls leading to another level of indirection, so from a performance perspective it's a negative mark.
2. The more fundamental problem is that you've botched the hasA vs isA association. If you have two classes that share a base class then that base class should be refactored into a component that can then be used as a member without polluting the class hierarchy. This leads to better composability since you can now pass this object around without pulling a whole class hierarchy with it.
You're welcome to use virtual inheritance all you want in your projects but much like knowing what subset of C++ to use(and what not) you'll never see it in code I work on.
No you haven't.
In many senses, C++ inheritance is just shorthand for composition. That's why things like private inheritance are useful. Through this lens, virtual inheritance is automatic composition in which multiple composed objects each have a pointer to some shared object (the virtual base). It doesn't mess with hasA vs. isA at all.
> knowing what subset of C++ to use
This idea that a good coding standard necessarily bans parts of C++ has done massive damage to the C++ community. The correct subset of C++ to use is C++. Turning off parts of the language is just a cheap way to look sagacious while infantilizing developers. Every feature has its place.
There's a been a fair number of projects I've worked on where exceptions and RTTI introduced too much memory/perf overhead so we explicitly didn't use them. I don't feel like we were worse off for not having them.
C++-without-exceptions is a very different and much worse language.
Considering LLVM takes the same stance[1] and they're the ones implementing language features that's good enough for me.
[1] http://llvm.org/docs/CodingStandards.html#do-not-use-rtti-or...
Well, it's a preference, not a hard requirement. I'll hold my nose and work on such a codebase if there are other reasons, like the project itself being very interesting.
> Considering LLVM takes the same stance
IMHO, that's a mistake. But LLVM is an example of a project that's compelling enough to work on despite what I consider a set of poor language choices.
Of course (C++14, possibly C++11):
Since this essentially simulates a method call, implicit conversions work, as does overloading "foo".As you have to implement "HasFoo" for every method you check, a macro will come in handy, say MAKE_METHOD_CHECK(Foo, bool, float)
I added some comments, feel free to ask if something is not clear :-)
If that's all you want just write:
When the derived class doesn't have any method "foo_impl" (or no "foo_impl" with a suitable signature), you will get a compile-time error.No need for the static_assert, that was just because KKKKkkkk1 asked whether checking for the existence of a method at compile-time was possible.
Compile-time polymorphism is essentially duck typing: If it quacks like a duck you can treat it as one. If it doesn't quack like a duck, but you still treat it as one you get a compiler error.
As the call is resolved at compile time, simply calling the function will cause a compile error if the derived class doesn't implement it. The error message might not be the prettiest, but there are ways to improve that.
I hope I will manage to try modules in MSVC before that time.
http://cppcast.com/2016/06/herb-sutter/
Trigraphs [1] are gone. Good riddance, they're just used for pointless pranks anyways. Otherwise they just seem to cause issues, there's always someone who didn't know about them at all.
Also "unexpected_ownership_move" err... "auto_ptr" is gone [2]. Yeah, I know, there's nothing inherently wrong with it and you knew how to use it correctly...
[1]: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n398...
[2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n419...
This also makes the standard smaller.
Man... Who do you work for? If I used that as a reason for a refactoring my boss would laugh at me (and he's technical) . I imagine his boss would glaze over for a bit and then ask him to leave his office.
Speaking as an engineer, some of us have a tendency to want to refactor and polish code past the point where we should ship it and move on to something else. Management also has a tendency to view refactoring as unproductive and hurtful to the company's bottom line. Both are very reasonable positions. In most cases, the best strategy tends to be in the middle somewhere.
The auto_ptr class is gone from C++17 because it is error-prone to use it and there are better alternatives. However, I don't need to explain the intricacies of auto_ptr to my boss. I can just say something like, "We want to keep up with the latest industry best practices and standards. Some simple changes to our code base will reduce the chance for bugs and reduce support costs, and make it easier to develop new features."
The fact that auto_ptr has been removed from the standard entirely sends a stronger signal that you really should stop using it. Which is a good signal to send.
It's why most C++ compilers these days don't even enable them by default. Kicking them out of the Standard is merely the recognition of that practice.
[0] https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#Removal...
See also: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n291...
It's remarkable that such systems still exist (and are apparently being updated, without their foundational cracks fixed) still today!
FFS, if you somehow find both of these to be true, preprocess your source to convert trigraphs to the corresponding glyphs, and to a character encoding that supports them. I can't possibly believe that they're running a C++17 compiler on a system that has no support for such a character set.
"auto [a , b , c] = getvalues();
"The braces are needed, getvalues returns a tuple. std::pair is not mentioned in the proposal, so its unclear if this works with pair, which is returned by the STL in some insert methods."
Destructured bindings will work with arrays; plain aggregate structs; and any class that offers a specialization of std::get<>(), so both std::tuple and std::pair are supported as a consequence. (C++11 added std::get<>() for std::pair).
Otherwise, if the expression std::tuple_size<E>::value is a well-formed integral constant expression, the number of elements in the identifier-list shall be equal to the value of that expression
(E is the return type of "getvalues" in squidbidness's example, the initializer-list is "a, b, c".)