Friday, June 7, 2013

FeedaMail: Comments for Sutter’s Mill

feedamail.com Comments for Sutter's Mill

Comment on C++ and Beyond: My material for December, and early-bird registration (through June 9) by Herb Sutter

@Alex: Brian’s announcement was only of a subset of features in VS2013. Much more, including C++ updates, will be announced at Build in three weeks.

The Express SKU is free, and always includes our latest C++ optimizing compiler with all the features we have implemented. VS subscription customers get updates for free for the life of their subscription, I think. Beyond that I’m not sure of other details, but the upgrade policy VCS 2013 will be announced and should be able to answer any other questions.

I tried very hard to be crisp and not imply anything beyond what we actually knew explicitly — but FWIW I notice even your question morphed from “free C++11″ at the start to became “free C++14″ by the end. Please no adding goalposts to what I actually said, or moving the goalposts even in the same question. :) I can summarize what we announced, and you can check the posted talk slides: At GoingNative Feb 2012, we announced that you shouldn’t expect to have to wait the usual 2-3 years between VS releases to get more C++11, that we would do more out-of-band releases (CTPs and/or RTMs) on a faster cadence, including but not limited to using them to deliver conformance features, and we’ve done that. And at Build in Nov 2012 we announced the Nov 2012 VC++ Compiler CTP and its new features, and promised that we’d share more updates in the first half of 2013, and we’ll do that this month at Build.

Some customers hoped/inferred that the CTP features would land in an Update; then after a while said that they would ship in an Update; and then most recently claimed that I had in fact announced they would ship in an Update. I actually didn’t say that, specifically because we didn’t know if we could get them into an Update and we didn’t want to promise something we maybe couldn’t do. But I’ll keep saying what we know when we know it and are sure, and will try to continue improving in communicating more clearly and your and everyone’s feedback on that is always appreciated.

Read More »

Comment on C++ and Beyond: My material for December, and early-bird registration (through June 9) by Alex

@Herb,

1) I was not moving the goalposts, the issue was and continues to be C++11 conformance. However, since the C++11 changes are minor, it may (wild guess) be easier for your team to ignore C++11 and do C++14 instead. I did not mean to imply that anything like that was promised but decided to ask about it just in case.

2) A CTP that comes without a go-live license is hardly a case of “and we've done that”.

3) Visual Studio is a bundle of features and a lot of people do not need all the new ones in VS2013 but just want a conforming compiler. To make a car analogy, I wouldn’t buy a new car just because I want satellite radio.

4) Your reply is confusing. You did talk about a shorted time frame to conformance and you also talked about free updates (in the same post, if I remember correctly) so was natural for people to connect those two together. With all due respect, but if it was not what you meant, then not saying it outright and leading us to believe the opposite was disingenuous.

Read More »

Comment on C++ and Beyond: My material for December, and early-bird registration (through June 9) by Herb Sutter

@Alex: 2) Well, I did say “a CTP or an RTM.” 4) Sorry, I didn’t mean to be confusing and I didn’t think I ever said free updates — can you point to the post? I’d like to fix it. Thanks!

Read More »

Comment on GotW #91 Solution: Smart Pointer Parameters by Jon

@Herb: If a function is going to decide at runtime whether to share ownership or not, should we still pass the shared_ptr by value or is const reference a legitimate choice? It seems to me that if we pass an lvalue by value and the called function decides not to share ownership, we’ve copied a share_ptr for no reason.

Read More »

Comment on GotW #90 Solution: Factories by Kai Koehne

I’m not sure recommending unique_ptr et al for every pointer out there is a good idea, because it will blow up debug symbol sizes. I did a quick test and replaced the pimpl pointer of an otherwise empty class with unique_ptr – for clang 3.2 that adds 30 additional debugging symbols to the .o file, for gcc 4.8 it’s even 60 (!). I can easily imagine this kills debugging performance in larger projects …

Any thoughts on this?

Read More »

Comment on GotW #90 Solution: Factories by Herb Sutter

@Kai: That’s an interesting question. I view it like other features such as template mangling or generating lambda function objects. The features are good for clarity and correctness, should be recommended, and will be used. Many C++ code bases have long routinely used custom nonstandard smart pointers already anyway. If sometimes a tool’s implementations has scalability trouble with a popular feature, if it causes a real problem then the tool needs to be improved. (However, for balance, there have been one or two complexity-inducing C++ features that caused tool trouble where it wasn’t fair to blame the tools, but we don’t have export any more and that was the main one.)

Read More »

Comment on GotW #91 Solution: Smart Pointer Parameters by Herb Sutter

@Jon: That’s probably a rare case but I think you’re right it’s worth calling out. Added, thanks.

Read More »

Comment on GotW #90: Factories by web page

I’m impressed, I must say. Rarely do I come across a blog that’s equally educative and amusing,
and let me tell you, you have hit the nail on the head.
The issue is an issue that not enough folks are speaking intelligently about.
I am very happy I found this in my search for something
regarding this.

Read More »

Comment on GotW #92 Solution: Auto Variables, Part 1 by davidphilliposter

typo “you really are declaring a your own new local variable” extra “a” (Feel free to delete this comment)

Read More »

Comment on GotW #92 Solution: Auto Variables, Part 1 by Herb Sutter

@davidphilliposter: Fixed, thanks. I’ll keep the comment, I like accountability and giving credit.

Read More »

Comment on GotW #92: Auto Variables, Part 1 by braincode23

The oldest functionnality in C++11 is the “auto” and the “decltype”

Read More »

Comment on GotW #92 Solution: Auto Variables, Part 1 by monamimani

I really don’t understand why f is a int* while h is int. That doesn’t make sense to me. Anybody can explain? To me I don’t see any common rule to this.

Thanks

Read More »

Comment on GotW #92 Solution: Auto Variables, Part 1 by Phil Barila

The first letter of the explanatory paragraph after:
“The type of i is const int*.”
is a stray ‘s’.

Read More »

Comment on GotW #93: Auto Variables, Part 2 by mttpd

http://herbsutter.com/2013/06/07/gotw-93-auto-variables-part-2/

1.(a) We can generalize the code from using `int` to other value_types stored in std::vector.

// On a side note: I usually prefer to use `it` for iterators and `i` for indexes for easy disambiguation.

However, since we’re relying on the RandomAccessIterator concept when we do `it += 2`, we can’t generalize beyond the types which models it (as long as we’re talking about the Standard), `std::vector`, `std::array`. and `std::deque` (an old C-style array would work, too).
While we could replace `it += 2` by twice-applied std::advance, this would have performance implications (no longer guaranteed O(1) on this op).

Overall, it’s worth remembering Scott Meyers’ advice from “Effective STL”: “Item 2: Beware the illusion of container-independent code.”

However, given that there are multiple types modeling RandomAccessContainer for which `traverse` makes sense, there’s a case for making our `traverse` a bit more generic:

  template <typename RandomAccessContainer>  void traverser( const RandomAccessContainer & v ) {      using std::begin;      using std::end;      for( auto it = begin(v); it != end(v); it += 2 )  

First, the error part (easily tested for 1-sized vector): since we’re traversing with non-unit stride, we have a potential out of bounds error here (stepping too far). First, we have to change the test condition (`it` relies on being `RandomAccessIterator` for this type of traversal anyway, so that’s fine; see the aforementioned “Item 2″):

for( auto it = begin(v); it < end(v); it += 2 )

That’s not the end of it — advancing iterator past the end is actually undefined behavior.
Credit goes to James McNellis for a solution in this case:

http://stackoverflow.com/questions/9387569/non-unit-iterator-stride-with-non-random-access-iterators

See also:

http://stackoverflow.com/questions/1057724/what-if-i-increment-an-iterator-by-2-when-it-points-onto-the-last-element-of-a-v

Note, that while `begin(v)` will work for `std::` containers thanks to ADL, it will not work for C-style arrays.
At the same time, simply replacing it with `std::begin` would be a bad idea, since that would prevent the user from applying `traverse` to user-defined containers (which obviously don’t live in `std::`).
Hence, analogously to what we do with `using std::swap` and `swap` in the copy-and-swap idiom, we pull in the `std` namespace into consideration with the using declaration, and keep using unqualified `begin`.
Analogous considerations apply to `end`.

Given all these issues, I’d actually *strongly* consider using indexes here — note that we won’t lose any genericity, since we’re relying on having a `RandomAccessContainer` anyway — again, to repeat Scott Meyers’ advice from “Effective STL”: “Item 2: Beware the illusion of container-independent code.”

Hence, after further consideration, I think I might possibly go against the grain here and suggest the following instead (together with including `cstddef`):

for( std::size_t i = 0; i < 0; i += 2 )

If one insists on using iterators here, I think we have to go Boost and use `boost::strided_range` / `boost::adaptors::strided`.
Example:

  // http://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/adaptors/reference/strided.html  // using C++14 polymorphic lambda    #include <boost/range/adaptor/strided.hpp>  #include <boost/range/algorithm/for_each.hpp>     template <typename RandomAccessContainer>  void traverser( const RandomAccessContainer & input ) {      using namespace boost::adaptors;      boost::for_each(          input | strided(2),          [](auto value) { /* std::cout << value; */ });  }  

To avoid unreadeable compiler diagnostics if our input cointainer’s type doesn’t model `RandomAccessContainer` concept:
- with concepts lite in C++14 we’d constrain on `RandomAccessContainer` (and/or `RandomAccessIterator`) explicitly, instead of just typing out a name.
- in C++11 we could add `static_assert` relying on the `iterator_category` being a `std::random_access_iterator_tag` and providing a readable error message otherwise.

1.(b)
Simply use uniform initialization:

vector<int> v1{5};

See also “Intuitive interface — Part I” on “Andrzej’s C++ blog” :-)

http://akrzemi1.wordpress.com/2013/06/05/intuitive-interface-part-i/

1.(c)
Here we see a case where the code using a hard-coded type has become more brittle — it’s not robust to changes in the return-type, which could lead to an unexpected object slicing.
Hence:

auto w { get_gadget() };

On a side note, perhaps it’s also a good idea to keep the standard convention of calling factories “make”:

auto w { make_gadget() };

1.(d)

`std::function` implies type-erasure and performance drop due to run-time operations, which is probably not what we want.
Lambda types are not specified, so to keep using these directly we _have_ to use auto:

auto get_size = [](vector<int> x) { return x.size(); };

It’s worth noting that beyond being unspecified, type names are also unique, so `decltype` wouldn’t work either.
See “Auto – A Necessary Evil?” by Roger Orr in the ACCU’s Overload Journal #115, June 2013.

On a side note, note that (for similar reasons) we’d also prefer to use `auto` if our right-hand side object was a forwarding call wrapper returned by `std::bind` — so, it’s not just needed for lambdas :-)

2.(a)

Can’t really see an application for `auto` here, I think `auto w { widget() }` might be going somewhat overboard (it’s not even shorter to type, don’t see any clarity gain).
// In either case, we’re relying on the `widget` modeling the `DefaultConstructible` concept.

2.(b)

Problem #1: using `int` for size is a horrid crime against humanity! :D

I would’ve used `std::size_t` from `cstddef`, but I can see a case where `auto` could also work here.
Not to be too optimistic, there’s a downside of using `auto` in a similar context:

  // WRONG: using `int` for size is bad and you should feel bad  for (int iWRONG = 0; iWRONG < v.size(); i += 2)  

now, let’s say we’d try to use `auto`:

  // STILL WRONG: using `int` for size is bad and you should feel bad  for (auto iWRONG = 0; iWRONG < v.size(); i += 2)  

The comment still stands, since the type of literal `0` is `int`!
Hence, here we’d have to use a specific type:

  for (std::size_t i = 0; i < v.size(); i += 2)  

2.(c)

Hard-coding `int` ignores the integral promotion and the “usual arithmetic conversions” (UAC) rules.
The proper result-type is given by the type trait `std::common_type`, with `decltype`-obtained types of `x` and `y`.
Given that it’s probably too much typing and explaining ;], let’s go with `auto` here:

auto total = x + y;

2.(d)

This could get tricky, since the UAC could imply a promotion-to-unsigned, making the later predicate `diff < 0` trivially always-false.
See Stephan T. Lavavej – Core C++, 7, Usual Arithmetic Conversions and Template Metaprogramming:

http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-7-of-n

See also:

http://kanooth.com/blog/2010/08/cpp-templates-usual-arithmetic-conversions.html

This won't do either:

if (x < y) { /*...*/ }

Compliant Solution from the CERT's INT02-CPP (which also explains how the above code is not robust to the integral promotion and UAC):

https://www.securecoding.cert.org/confluence/display/cplusplus/INT02-CPP.+Understand+integer+conversion+rules

Given the C++11's type traits, we can modify the above solution so that the argument to `static_cast` is obtained using `std::make_signed`:

http://en.cppreference.com/w/cpp/types/make_signed

2.(e)

Well, here the intent is unclear, since the truncation from `double` (implied by the `42,0` literal) to `int` was possibly desired — in this case, however, an explicit `static_cast` would be in order (for clarity).

If the truncation is undesired, we'd be better off with the following:

auto i = f(1,2,3) * 42.0;

Read More »
 
Delievered to you by Feedamail.
Unsubscribe

No comments:

Post a Comment