Le 08/12/2017 à 21:40, Ian Collins a écrit :
>
>
> Very true, but unfounded criticism will never be well received. Rather
> than snipping you should take heed of Richard's main point about C++17:
>
> "The irony is that the new features and "bloat" are very much in the
> same vein as C++11: they make lots of code simpler and more uniform."
>
Look, constexpr if, at
https://medium.com/@LoopPerfect/c-17-vs-c-14-if-constexpr-b518982bb1e2
That piece explain us why this improvement to C++ is necessary. You have
code like this in C++ 2014.
template<unsigned n>
struct Arg {
template<class X, class…Xs>
constexpr auto operator()(X x, Xs…xs) {
return Arg<n-1>{}(xs…);
}
};
Not very readable, I agree with the author of that piece. And that is
replaced by:
template<unsigned n>
struct Get {
template<class X, class…Xs>
constexpr auto operator()(X x, Xs…xs) {
if constexpr(n > sizeof…(xs) ) {
return;
} else if constexpr(n > 0) {
return Get<n-1>{}(xs…);
} else {
return x;
}
}
};
in C++ 2017.
The use case is:
// arg<2>(0,1,2,3,4,5) == 2;
OK. You want to access the arguments of a function *by position*. Using
*names* for arguments is much better in my humble opinion, and both the
example and the solution in C++ 2017 can't escape the fact that is much
better to access arguments by their names... if any. In the case of
functions with a variable arguments list, you can (and should) use
default arguments for them, i.e. documented default args readable in the
function declaration.
What strikes me is that the only use case that the author tried to
figure out was a solution to a non-existing need: accessing your
arguments by a hard coded number.
Let's go on to the second case where the improvements should be needed.
C++ 2014:
template<class T>
auto compute(T x) -> decltype( enable_if_t< supportsAPI(T{}), int>{}) {
return x.Method();
}
You have to define the negative method that I do not show here since it
differs by a "!" only, in the condition above.
C++ 2017:
template<class T>
int compute(T x) {
if constexpr( supportsAPI(T{}) ) {
// only gets compiled if the condition is true
return x.Method();
} else {
return 0;
}
}
Yes. Obviously writing:
auto compute(T x) -> decltype( enable_if_t< supportsAPI(T{}), int>{})
is longer than
if constexpr( supportsAPI(T{}) )
Neat. Is that, however, a real need for so many programmers that the
whole language needs to be updated to support a shorter construct?
And what about C?
#if defined(API_3_5_8)
#endif
Yes but simple solutions (used everywhere) need to be updated and
rewritten in the new way...
This is what I mean with "featurism". A new feature of 2014 needs yet
another new feature in 2017 to be usable in a very terse way. And let's
go on adding features that will need more other stuff like this in 2020.
Many people will say here that the examples (the use cases) were badly
choosen. OK, but why can't the author figure out a better use case,
Why those use cases are so difficult to figure out???
Because they are very few, and even then, dangerous. Accessing arguments
by a bare index is an error in software construction, it leads to
illisible programs!
Argument NAMES should be used.
Shouldn't any new addition to C++ be justified by USE CASES???
By a survey of programmers that asked for that specific feature to be added?
If the features added are really needed by the programmers, the people
writing those descriptions wouldn't need to try to find something: it
would be obvvious to anyone that that is needed and why.
That is not the case here, so my thesis that manyt of these changes are
just bloat stands.
jacob