
Final features of C++17 - meetingcpp
https://meetingcpp.com/index.php/br/items/final-features-of-c17.html
======
vardump
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...

[1]: [http://www.open-
std.org/JTC1/SC22/WG21/docs/papers/2014/n398...](http://www.open-
std.org/JTC1/SC22/WG21/docs/papers/2014/n3981.html)

[2]: [http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2014/n419...](http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2014/n4190.htm)

~~~
quotemstr
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.

~~~
klodolph
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.

This also makes the standard smaller.

~~~
EpicEng
>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.

~~~
klodolph
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.

------
BinaryIdiot
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).

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...](http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2016/n4588.pdf)

~~~
quotemstr
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.

~~~
EpicEng
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.

~~~
nambit
[https://github.com/mrtazz/restclient-
cpp](https://github.com/mrtazz/restclient-cpp) ? 2 LOC. Wraps libcurl.

~~~
EpicEng
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?

------
cm3
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.

------
lorenzhs
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.

~~~
toth
I agree that constexpr if looks great. I am confused about the decision on how
to handle static_assert. It seems that

    
    
        if constexpr (false) { static_assert(false); }
    

Will fail to compile because the static_assert will trigger. This seems
strange to me, anybody have an idea what the reasoning here is?

~~~
lorenzhs
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

    
    
        if constexpr (foo) {
            static_assert(!foo || /* assertion */);
        } else {
            static_assert(foo || /* assertion */);
        }
    

(this gets ugly fast with lots of else-ifs, but it's a workaround - I don't
know why you'd ever need it, though)

~~~
toth
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:

    
    
        template<typename T> 
        void func(T x) {
            if constexpr ( std::is_same< T, ClassWithMemberF>::value ) {
                x.f();
            }
        }
    

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...

~~~
RcouF1uZ4gsC
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

~~~
toth
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.

------
setra
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.

~~~
quotemstr
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.

~~~
n00b101
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.

~~~
meetingcpp
boost::variant is 12 years old, the std::variant version is not based on the
actual design nor is it a copy of the boost implementation.

The interface is very similar, but the implementation is ofc using C++17 and
not C++03.

~~~
rleigh
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.

------
KKKKkkkk1
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?

~~~
quotemstr
> adding a compile-time sublanguage.

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?

~~~
vvanders
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.

~~~
bubuga
> 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.

~~~
vvanders
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.

~~~
quotemstr
> you've botched the hasA vs isA association

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.

~~~
vvanders
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.

~~~
quotemstr
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.

~~~
vvanders
If you're interested in limiting your market, there's a whole embedded and
high performance space where this is critical.

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...](http://llvm.org/docs/CodingStandards.html#do-not-use-rtti-or-
exceptions)

~~~
quotemstr
> 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.

------
squidbidness
To clarify a question raised in this write-up:

"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).

~~~
ant6n
What if the number of lhs values don't match the number of rhs values?

~~~
Kristine1975
Compile-time error:

 _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".)

------
corysama
[http://cppcast.com](http://cppcast.com) just had a great interview with Herb
Sutter where he talked about many of these features.

[http://cppcast.com/2016/06/herb-sutter/](http://cppcast.com/2016/06/herb-
sutter/)

~~~
ranit
The link is right there in the first paragraph :-)

------
jokoon
So the next standard will be in 2020 ?

I hope I will manage to try modules in MSVC before that time.

~~~
Kristine1975
That seems to be the plan:
[https://isocpp.org/std/status](https://isocpp.org/std/status)

------
vvanders
Really looking forward to auto templates, so annoying to have to specify type
signatures in lambdas when most other languages don't require it.

~~~
Kristine1975
Lambdas support that in C++14 (generic lambdas/polymorphic lambdas).

~~~
vvanders
Ah shoot, you're right. Not sure how I got them confused.

------
agumonkey
Variant, destructuring, template auto.

------
quotemstr
Yet memcpy(0, 0, 0) is still undefined behavior? For shame.

~~~
halayli
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.

~~~
vardump
Strictly interpreting true, but grandparent's point is very valid.

It's used everywhere in real life C++ code.

quotemstr got a very good point and I'm grateful for the heads up.

~~~
halayli
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.

~~~
Kristine1975
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).

C++ is not 100% compatible with C.

