Comment on GotW #92 Solution: Auto Variables, Part 1 by abigagli
Great article as usual. I just found a bit confusing the example for the case of “h”. If I’m correct, const T& is not a case of top-level const, so in case “h” what happens is actually that reference is stripped off _AND THEN_ what remains is a top level const that gets stripped as such. Am I right? Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Herb Sutter
@Phil: Fixed, thanks. @Ralph: Good suggestion. I was trying to keep it simple, but volatile and && should be mentioned up front. Updated. @nosenseetal: That's very kind, thank you, but I don't accept donations. I've also never run any ads. I have always published my GotW and other articles for free online, and only the final print/e-book versions have been for sale as they're done through a commercial magazine or book publisher. (Magazines, remember those? How quaint! We do miss C++ Report…) @Marcel: Thanks, and I've adjusted the layout of the table to make things clearer. Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Marcel Wid
I like to think about auto type deduction in terms of template argument deduction (@Herb: You should replace “parameter” by “argument” in the heading of the 2nd column). The above table may be extended to auto x = expr; template<class U> void f(U t); f(expr); //(1) const auto x = expr; template<class U> void f(const U t); f(expr); //(2) auto& x = expr; template<class U> void f(U& t); f(expr); //(3) const auto& x = expr; template<class U> void f(const U& t); f(expr); //(4) auto&& x = expr; template<class U> void f(U&& t); f(expr); //(5) const auto&& x = expr; template<class U> void f(const U&& t); f(expr); //(6)If expr has type “reference to T”, then this type is adjusted to “T” prior to any further analysis. This has nothing to do with auto, this is a general rule in C++. For auto type deduction this means that we can ignore any reference-ness on expr. We denote this adjusted type of expr by A. To further analyse what’s going on behind the scene, it is comfortable to denote the parameter type of f by P, for example in case (4) above P is “const U&”, in case (5) it is “U&&”. Now we have to distinguish between the following cases: - P is not a reference type (cases (1) and (2) above): 1. If A is an array or function type, A is replaced by the pointer resulting from array-to-pointer or function-to-pointer conversion int a[7]; const int b[7]; auto x = a; auto y = b;then x is of type int* and y of type const int*. 2. If A is a cv-qualified type, the the cv-qualifiers are ignored. const int& cir = 0; auto h = cir;Here cir has type “reference to const int”. This is adjusted to “const int” (=A) and now const is ignored and the type of h is int. - If P is cv-qualified the top-level cv-qualifiers are ignored for type deduction (case (2) above). int& ir = 0; const auto x = ir;Here again, & is dropped from ir and const is ignored, so we have to determine U such that “f(int) = f(U)”, hence “U = int” and the type of x is const int. Now it gets a bit more involved: - If P is a reference type, type referred to by P is used for type deduction (and if this resulting type is cv-qualified, the cv-qualifiers are ignored). If P is an rvalue reference to a cv-unqualified template parameter and the argument is an lvalue, the type "lvalue reference to A" is used in place of A for type deduction. const double& rd = 1.0; int&& ri = 0; auto&& x = rd; auto&& y = ri;Here we are in case (5). P is an rvalue reference to a cv-unqualified template parameter (U&&) and the argument is an lvalue (rd), so A (which is “const int”, note that here const is not dropped!) gets replaced by “const double&” and U is deduced to be “const double&”. Now reference collapsing comes in (& && becomes &) and x is of type const double&. Similarly, y is of type int& (note that ri is an lvalue). int&& ri = 0; const auto&& y = ri;Here we are in case (6) and get a compiler error. Why? P is an rvalue reference to a cv-QUALIFIED template parameter. After dropping & and const from P (A is int), we have to find U such that “f(U) = f(int)”. Hence “U = int”. The type of y becomes “const int&&”, but binding an lvalue (ri) to an rvalue reference is not allowed. const int& cir = 0; auto& x = cir;Here we are in case (3). A is “const int” and we have to deduce U such that “f(const int) = f(U)”, thus “U = const int”. The type of x is const int&. I hope, this helps clarifying how auto works. Read More »
Comment on GotW #93: Auto Variables, Part 2 by Johan Oudinet
@mttpd: Thanks for your comment. I’ve learnt a lot by reading it ;-) To come back on David’s suggestion, instead of: auto w = get_gadget(); I would have used: auto w = widget { get_gadget() }; making then explicit that I want w to be a widget object. This is similar to what have been done in 2a.1 from http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/ However, I don’t have a good example why it might be important to force w to be of type widget instead of gadget. As you said, if gadget IS-A widget, we are still safe in using the gadget object with anything that wants a widget. The only reason could be if there is no implicit conversion from gadget to widget but then the original code won’t compile. Read More »
Comment on GotW #90: Factories by Sebastian Zander
1. The problem is it’s a raw pointer. The pointer is, presumably, dynamically allocated and it is not clear who is responsible for its deletion. 2. Because it’s a widget I would say std::shared_ptr is the best. This way we could pass it to other classes, functions, which we couldn’t do with std::unique_ptr. If we weren’t meant to pass it around std::unique_ptr would be preferable. 3. Because the callers are all using auto w = load_widget(some_ID)And because std::unique_ptr and std::shared_ptr both are written to be used like a pointer would it wouldn’t make a difference anywhere (except we couldn’t use delete on them!). 4. Probably the recommended type would be a straight up object, and we could move it out of the function. We could make the load_widget be a template function over the type of widget we wish to create: template <typename WidgetType> WidgetType load_widget()Because the type is not polymorphic there is no reason to bind it to a pointer to a base object. Read More »
Comment on GotW #93: Auto Variables, Part 2 by mttpd
Correction: no, std::cbegin or std::cend won’t be necessary here, since the argument’s type is already const and thus the right, const-correct overloads of std::begin and std::end shall be chosen.Read More »
Comment on GotW #93: Auto Variables, Part 2 by mttpd
That’s a good catch, afrantzis! After thinking about it, this makes me tend to prefer the index-based solution (with std::size_t) or even better Boost.Range one (it’s better and IMO is to be preferred since it’s less error-prone and more expressive, analogously to how using STL algorithms is less error-prone & more expressive than hand-coded loops in general) — since, in addition to auto, I think we should also use std::cbegin and std::cend (from C++14) instead of their non-const counterparts.Read More »
Comment on GotW #93: Auto Variables, Part 2 by afrantzis
1(a) The code is incorrect, since we are trying to get a non-const iterator to a const container. By using auto we would have avoided this programming error; the expected (and safe) const_iterator type would have been chosen. Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Mathias Stearn
It might be worth adding the following examples. After reading this article I felt the need to test these cases since auto expands to “const int” which does have a top-level const even though the full types of g2 and h2 don’t. const int ci = val; auto g = ci; auto& g2 = ci; const int& cir = val; auto h = cir; auto& h2 = cir;Also, I’m curious about auto&&. I think it would only be an rvalue-ref when the right hand side was a value or rvalue-ref returned from a function. Is there any detail I’m missing? Read More »
Comment on GotW #91 Solution: Smart Pointer Parameters by Mathias Stearn
What do you think of using something like ptr [1] which is usable like a T* but is implicitly convertible from any smart pointer and clearly marks non-owning semantics? I’ve found that in code that uses smart pointers, functions that take a bare pointer are annoying because you have to call get(), breaking the abstraction. It also has a nice side benefit of less visual ambiguity between const ptr and ptr. On the related issue of pointer returns, do you know why covariant return support wasn’t added for smart pointers? It seems like a clone() method would have to choose between better type-safety but using a raw owning pointer or returning a smart pointer and requiring casts. [1] https://gist.github.com/RedBeard0531/5736292 (written for C++98 + boost) Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by nosenseetal
@Herb did you consider putting donate button on your site… I personally dont really buy books, but I appreciate your work with refresnihg GotW and new GotWs and I would like to have option to show my appreciation with my euros. :D IDK if other ppl agree so this is just IMO :D Read More »
Comment on GotW #92: Auto Variables, Part 1 by David Thomas
This is a crazy test int& a = c;. This is more.Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Amali
The image was blocked in my system, now I can see the image. Read More »
Comment on GotW #92: Auto Variables, Part 1 by David Thomas
@herb: wordpress supports <code> in comments so folks can add code inline to prose. Read More »
Comment on GotW #92: Auto Variables, Part 1 by David Thomas
delete this monospaced - word with and I Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Amali
@Herb, The table you mentioned for question 4 is only visible in this post in your website, but not in the post I received in my inbox. I wonder why? Read More »
Comment on GotW #92: Auto Variables, Part 1 by David Thomas
delete this [pre]monspaced[/pre] Read More »
Comment on GotW #93: Auto Variables, Part 2 by mttpd
David: it’s not necessarily less safe, since the following assumption may not hold (it is not guaranteed): “presumably then `w` is a functioning `widget`.” If the `gadget` & `widget` types are in the IS-A relationship, we’re facing the so-called slicing problem, see: http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c That being said, your “As long,,,” explanation also applies to the object slicing problem and is a nice description :-) Read More »
Comment on GotW #93: Auto Variables, Part 2 by David Thornley
1. In // (c) gadget get_gadget(); // ... widget w = get_gadget();changing the variable declaration to auto w = get_gadget();could be less safe. In the first case, we get a compile error unless we have an automatic conversion from gadget to widget. If we have one, there is no error, but presumably then w is a functioning widget. If we write w.Foo(), we know we’re using widget::Foo(). Either there’s a compiler error or there are no surprises. In the second case, the type of w is gadget, but we don’t realize that. We’re presumably assuming the type of w is widget. As long as we don’t call any function that doesn’t have a counterpart of the same name in gadget, we’re not going to get a compile error, and we’re going to be mistaken in what we’re calling. If we write w.Foo(), we’re calling gadget::Foo(), which may do something unexpected if we’re unlucky. Read More »
Comment on GotW #93: Auto Variables, Part 2 by mttpd
Again, assuming C++14 with polymorphic lambdas supporting universal references, let’s change the code in 1.(d) to: auto get_size = [](auto && x) { return x.size(); };
(for the reasons see my previous comment).Read More »
Comment on GotW #93: Auto Variables, Part 2 by mttpd
Come to think of it, I’d also replace the lambda in 1.(a) with the following (still C++14): [](const auto & value) { /* std::cout << value; */ }
or, if the C++14 polymorphic lambdas support universal references (which they hopefully do), simply:[](auto && value) { /* std::cout << value; */ }
(for automatic const-correctness with less typing; and to handle a certain nasty proxy case ;]).Read More »
Comment on GotW #93: Auto Variables, Part 2 by mttpd
Sigh… one more typo :-) This time, in the code in “1.(a)”, which instead of for( std::size_t i = 0; i < 0; i += 2 )should say for( std::size_t i = 0; i < v.size(); i += 2 )Giving how easy it is to make typos in this context, I’m becoming more and more inclined toward recommending the Boost.Range solution here :-) Let me use this opportunity to make one more note on the genericity — the Boost.Range solution in fact only requires a type that is a model of Single Pass Range. This corresponds to an iterator type being a model of Single Pass Iterator (which has even less requirements than a Forward Traversal iterator, let alone a Random Access Iterator). One could ask then, isn’t requiring a RandomAccessContainer an over-specification? Well, this is similar to considering whether we should replace `it += 2` with `std::advance(it, 2)`. After thinking about it, I’d say that there are no good *general* answers here, since it depends on the use case; the trade-offs to consider are as follows: - either: clear-cut complexity guarantees (`it += 2` is either O(1) or doesn’t compile if we keep the requirement), - or: increased level of genericity (dropping the requirement; the cost of `std::advance(it, 2)` depends on the iterator category, which depends on the container). If we go down the road of increased genericity, we’d have to use a `SinglePassRange` concept instead (or `SinglePassContainer` / `SinglePassIterator` where applicable) and carefully document the performance impact of having types modeling a different levels of refinement of this concept. Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Ralph Tandetzky
Maybe you should mention that volatile is also stripped from the right hand side type for completeness. This highlights the symmetry of const and volatile. Are there any other things that can be stripped? In the second section you say “such as top-level const-ness and reference-ness”. Instead you could say “which are top-level const-ness, volatile-ness and reference-ness”. Just a thought. Read More »
Comment on GotW #92 Solution: Auto Variables, Part 1 by Leo
@monamimani Take a look at what Herb wrote about e. Similar reasoning applies to h. cir is a reference to val and it would not allow to change val. But auto h = cir;is equivalent to auto h = val;In the case of f ip is not a different name for val. It’s a pointer to a location in memory, it contains an address. auto f = ip;assigns to f the address contained in ip, not the integer contained in val. 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 #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 #93: Auto Variables, Part 2 by mttpd
// Note: posting _once_ again (I *really* wish there was an “edit” option at this point), feel free to remove my previous comments (and this note), was hoping to avoid the hassle with URL formatting, obviously didn’t work; also fixed a few typos and a bug; sorry for any inconvenience this might have caused :-) 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 model 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 `std::advance(it, 2)`, 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 an 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 Now, let me explain the using declarations `using std::begin` and `using std::end`. 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 it 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 naming the 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. [PDF] http://accu.org/var/uploads/journals/Overload115.pdf 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 an `int` for a variable storing the 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/complacent, however, there’s a downside to 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 just 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. To make this even more fun, it's actually implementation defined whether, say, `long int` or `unsigned int` "wins" in the promotion battle :-) 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 rules):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 be given 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` could possibly have been 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 »
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 Herb Sutter
@davidphilliposter: Fixed, thanks. I’ll keep the comment, I like accountability and giving credit. 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 #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 Solution: Factories by Herb Sutter
@Kai: Definitely not recommending smart pointers for everything, in particular not for most parameters; see GotW #91. But overall tool support is 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 #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 #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 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 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: 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 information 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 GotW #6b Solution: Const-Correctness, Part 2 by Herb Sutter
@Mathias: Excellent point, fixed. Thanks. Read More »
Comment on C++ and Beyond: My material for December, and early-bird registration (through June 9) by Alex
@Herb, thank you for your reply, but there is a bit of a difference between snarky remarks and delivered features. I am very concerned about the standard support in VS2012 because I invested a lot of efforts to persuade my company to purchase VS2012 (for more than 50 developers), based on my interpretation of your promise — that VS2012 will get full C++11 compatibility via free updates (and I am sure that I was not the only person to interpret it this way). Now, I see Brian Harry announcing VS2013 (http://blogs.msdn.com/b/bharry/archive/2013/06/03/visual-studio-2013.aspx) and, given my previous experience with MS, I suspect that you (plural) will prefer pushing users to buy the new version rather than putting out free upgrades to the older one. Profits always trump “the right thing to do”. Should this happen, I am fairly convinced that the following will happen: 1. My credibility within the company will be shot (best case scenario). 2. We will start transitioning to a free compiler (likely GCC or CLang) and eventually away from Windows and other MS products (the main reason that the developers are on Windows 7 is to run Visual Studio). I have no intention of “scissors headlocking” you or anything but I do believe that you have the moral obligation to answer the following: 1. Will there be a free upgrade to VS2012 to provide full C++14 compatibility (in whatever time-frame)? 2. If not, will there be a free upgrade to VS2012 to provide full C++11 compatibility (in whatever time-frame)? 3. If not, what level of compatibility should we expect? Best regards, Alex. Read More »
Comment on GotW #91 Solution: Smart Pointer Parameters by Brian Fiete
Re: #2 (correctness) – even without changing the state of the calling function, passing a shared_ptr by reference can be hazardous if the function is able to remove the shared_ptr reference that was passed to it. A trivial case is below (results in a crash), but one can easily imagine a less trivial case — say, if the function were to run some validation on the data passed to it which could result in a new instantiation of that data… struct IntArrayContainer { shared_ptr<vector<int>> mIntArray; }; IntArrayContainer* gIntArrayContainer; int GetFirstValueFrom(shared_ptr<vector<int>>& intArray) { delete gIntArrayContainer; return (*intArray)[0]; } void main() { gIntArrayContainer = new IntArrayContainer(); gIntArrayContainer->mIntArray = shared_ptr<vector<int>>(new vector<int>(1, 1)); printf("First: %d\n", GetFirstValueFrom(gIntArrayContainer->mIntArray)); }
Read More »
Comment on GotW #6b Solution: Const-Correctness, Part 2 by Mathias Stearn
Wouldn’t the move operations need to set other.area to -1 since a cached area would no longer apply to the now-empty points vector? Read More »
Comment on GotW #1 Solution: Variable Initialization – or Is It? by dengos (@Cheng_Wer)
@Seungbum Woo @Herb Sutter Just for curious, i check Seungbum’s code under archlinux_64, g++4.8.1 main() { ... F f{a}; // #2 f.test(); // #3 } |
by initialization v in {} way(#1), the output will be:
2
[1] 8742 segmentation fault (core dumped) ./a.out
gdb a.out turn out that, after execution of #2, the f object in memory look like this:
(gdb) p f
$1 = {v = std::vector of length 2, capacity 2 = {0, 0}}
but still can’t figure out why the segmentation fault.
Read More »
Comment on GotW #91 Solution: Smart Pointer Parameters by Kamil Rojewski
I have a question about example (c). Wouldn’t it be better to use rvalue ref to unique_ptr instead of pass-by-value? It still requires to pass an explicit unique_ptr, but it shows an expcilit move is done, instead of implicit by passing to the parmateter value.
Read More »
Comment on GotW #91 Solution: Smart Pointer Parameters by Leszek Swirski
@Jon: I have considered it, but a similar proposal was rejected in 2003, because (as I understand it), even people who liked the syntax didn’t like the fact that this was essentially optional, rather than a language change (cf. Ada, C#). The argument was that for
f(out(x),y)you technically still don’t know if y is mutable or not, because the evil library writer could still be using normal references.
http://lists.boost.org/Archives/boost/2003/04/47180.php
Read More »
Comment on GotW #92: Auto Variables, Part 1 by GonzaloBG
I think about auto in the same way as I think about TAD, decltype on the other hand…
Read More »
Comment on GotW #89 Solution: Smart Pointers by Herb Sutter GotW89: Smart Pointers | musingstudio
[…] Sutter’s GotW89 Smart Pointers post includes good reasons to use make_shared/make_unique instead of naked new. Avoiding memory […]
Read More »
Comment on GotW #91 Solution: Smart Pointer Parameters by decourse
As I noted in a comment on the question, there is another use for (d). Some functions may choose to either take or not take ownership of an object by criteria to be decided at run-time, perhaps by inspecting the object itself. Think of a “chain of responsibility” pattern, for example.
Read More »
Comment on GotW #91 Solution: Smart Pointer Parameters by Herb Sutter
@Jon: This is better in the case where you do get an rvalue, and the default guidance to “pass by value then move as needed” doesn’t apply just to smart pointers but to any type that’s cheaper to move than copy. And yes, my opinion has changed. Basically that came from paranoia about a different optimization that doesn’t apply to standard C++ code (something we encountered designing C++/CX that can apply to the underlying implementation of refcounted ^’s but I now realize doesn’t apply to shared_ptrs in normal C++ code).
Read More »
Comment on GotW #89: Smart Pointers by Hawlin
I often use the unique_ptr, because it allows the responsibility of the single object (and its security), I also use it because it can destroy the object when it is pointed more accessible. and the management of life of the equipment.
Read More »
Comment on GotW #89 Solution: Smart Pointers by Marco
@Herb: Another question popped up when looking at figure 2(b): make_shared allocates one single block of memory holding the strong and weak reference counters and the object itself. So if there are no shared_ptr left, but at least one weak_ptr, the whole block cannot be released, correct? So if one’s handling large objects and using shared_ptr the recommendation should be not to use make_shared? Or is there something I’m missing?
Read More »
Comment on C++ and Beyond: My material for December, and early-bird registration (through June 9) by Alex
@Herb,
2) I believe that the exact statement was:
As for Microsoft's product specifically, we've said we're planning to ship out-of-band releases "soon after VC++ 2012″ (which is soon indeed now!) and particularly that we want to take advantage of that capability first to deliver more and more batches of C++11 features, first in a CTP (community tech preview) or similar form.
Saying “first” implies a “second”.
4) OK, let’s set the “free” issue aside then. I may have been inferring too much.
Can we expect an update (either free or paid) that will bring C++11 (or C++14) compatibility to VS2012?
Best regards,
Alex.
Read More »
Comment on C++ and Beyond: My material for December, and early-bird registration (through June 9) by Herb Sutter
@Alex: Thanks, I was just double-checking that talk again too. Indeed, we did miss a promise that was on the slide which was to deliver “more batches” in the first half of 2013, and I should speak to that in my Build talk this month. At that time, we said that because we had intended to produce another CTP in spring. Two things happened: When turning the crank in about a year on VS 2013 became a reality we had to focus on that release vehicle to make sure the features for it were up to release quality (bug bar, Intellisense support, static analysis support, libraries support, and such). Also, it took us longer than expected to stabilize variadic templates, because for us part of doing C++11 is that we need to rewrite parts of our compiler that are up to 30 years old — for example, unlike GCC and Clang, our compiler has never had an AST, and you kinda sorta need that for some C++11 features — and in retrospect variadic templates would have consumed much less effort if we’d done it after waiting for a little more of the AST-related rework instead of doing it in the existing codebase which caused more complexity and a longer bug tail. Although we missed on our intent to deliver another CTP in the spring for those two main reasons, we’re following through on the spirit of what we promised which is applying more resources to implement and test C++11 features, do ongoing rejuvenation of our compiler codebase to better support C++11, and release more CTP and RTM builds containing more conformance features on a faster-than-every-2-3-year cadence, and I’ll have more news to share on those at Build. We got beaten on this expectation by being a little more transparent than a company this size normally is, but I think erring on the side of transparency is still the right place to be and we’ll keep doing that, but hopefully better by letting customers know earlier if we can’t meet a deadline, and by being more explicit about how we want to show progress — such as addressing expectations about when features will appear (because we didn’t say otherwise, many assumed they’d be in an Update, so we need to communicate better).
Re versions and upgrades: Note that part of the confusion is that we’re kind of “shifting worlds” with the way and frequency we deliver Visual Studio, so there’s a transition period for us and for customers to learn and get used to the new model and cycle. Instead of shipping a big lump every 2-3 years with a sort-of-annual service pack as we’ve done for a long time, we’re moving to a cadence of smaller more regular releases plus Updates in between. VS2013 is the first of those regular releases, so it shouldn’t be viewed the same as the VS2012 which was the last of the old-style big-lump releases for example, even though I realize its naming initially makes it sound like that until we learn and get used to the new pattern. Details of the future VS release roadmap and upgrade policy and such will be announced when and as the VS folks have them available; I can speak directly for the VC++ part of the product, and then how that gets shipped in an actual release depends on the cadence of the larger VS product.
Thanks for your support of our product, and I hope that the news at Build and onward will be satisfying and helpful.
Read More »
| Delievered to you by Feedamail. Unsubscribe |