| ||||
| Comment on GotW #5 Solution: Overriding Virtual Functions by Caleb Huitt
Surely given your previous comments (and my own lazy inclinations), this line: unique_ptr<base> pb = make_unique<derived>(); could become: auto pb = make_unique<derived>();Read More » Comment on GotW #5 Solution: Overriding Virtual Functions by Simon L
Apologies, that was meant to read that on the second line pb’s type will be unique_ptr<derived>Read More » Comment on GotW #5 Solution: Overriding Virtual Functions by Simon L
Caleb, in your two lines the type of pb will be different. in the second line it will be a unique_ptr. If that’s what you want, fine, but it’s not the same as the first line, which includes an implicit conversion. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by KrzaQ
I’m pretty sure that base:f; should be base::f; in “Well, remember that derived doesn't declare using base:f; to bring the base functions named f into scope”. I’m sorry if this isn’t the way to report typos. While I’m at it, let me thank you for restarting GotW, I find your challenges stimulating. Read More »Comment on GotW #6a: Const-Correctness, Part 1 by zahirtezcan (@zahirtezcan)
http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank ? :) Read More »Comment on GotW #5: Overriding Virtual Functions by Tom
Some times Curiously Recurring Template Pattern can help too. #include <iostream> #include <complex> using namespace std; template <class Derived> class baseT { Derived& derived() { return *static_cast<Derived*>(this); } public: void f( int ) { cout << "base::f(int)" << endl; } void f( double ) { cout << "base::f(double)" << endl; } void g( int i ) { derived().g(i); } void g( ) { derived().g(); } }; class base : public baseT<base> { public: void g( int i ) { cout << i << endl; } void g( ) { g(10); } }; class derived : public baseT<derived> { public: using baseT<derived>::f; //make f() from base visible here void f( const complex<double> & ) { cout << "derived::f(complex)" << endl; } void g( int i ) { cout << "derived::g() " << i << endl; } void g( ) { g(20); } }; int main() { base b; derived d; auto & rb = d; b.f(1.0); //base::f(double) d.f(1.0); //base::f(double) rb.f(1.0); //base::f(double) b.g(); //10 d.g(); //derived::g() 20 rb.g(); //derived::g() 20 return 0; } Read More » Comment on GotW #5 Solution: Overriding Virtual Functions by Arthur Langereis
@Caleb, he’s explicit here as make_unique would return a unique_ptr to derived, not to base, which is what he wants here and which is the equivalent of the original code. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by mttpd
void main() — ouch! I don’t think this was really intended here! ;-) Read More »Comment on GotW #6a: Const-Correctness, Part 1 by Chris Vine
@zahirtezcan: Beware of that presentation though. The issues are not clear cut. First, 17.6.5.9/3 of the C++11 standard provides an absolute preclusion of bitwise modification of an object through a const argument, irrespective of whether it would be thread-safe to do so because there is internal synchronization so it can safely be made mutable. Possibly 17.6.5.9/7 is intended to permit this, but it is not clear (to me at least) that it qualifies 17.6.5.9/3, nor is is it clear to me what is meant by “implementations” in relation to user provided objects. Secondly, just because a library function taking an object by const reference is guaranteed by 17.6.5.9/3 not to modify the object does not of itself make a read operation made by that function thread safe. If an object is visible to another thread, the read is only thread safe if the other thread does not modify it or there is synchronization. const does not therefore seem to me to mean “thread-safe” in anything other than a significantly qualified sense. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Herb Sutter
@KrzaQ: Yup, : should be :: — fixed, thanks. @mttpd: Yup, fixed. The original GotW had “void main()” and made a pedantic point about its conformance, and I decided it was a distraction and removed it by changing it to “int main()” in the question, but forgot to also update the solution. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by TheMatto
make_unique: are we using C++1y here? Read More »Comment on GotW #6a: Const-Correctness, Part 1 by Marshall Clow
I’ll start with const, when used in a parameter list. void foo ( const std::string &s ) { /* ... */ } Nothing in ‘foo’ should change ‘s’; no changing of public members, no calling of non-const member functions, no passing of ‘foo’ to a function that takes a non-const reference. Notes: Comment on GotW #5 Solution: Overriding Virtual Functions by TheMatto
Clarification: Where did make_unique come from? C++1y? Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Bjarke Hammersholt Roune
When you are using NVI for a base class A with a function foo(), and a sub class B wants to call foo() on itself, does B call the public or private version of foo()? It seems to me that the answer to that depends on what A is doing in the public foo() and the needs of B – if B needs A to do what it does in the public interface, then B should call the public interface and otherwise B should call the private interface. If that is true, then NVI creates a new source of bugs where sub class writers now have the option of calling the wrong interface. Is NVI normally done in some way that side-steps this issue? Read More »Comment on GotW #6a: Const-Correctness, Part 1 by mttpd
A proposed follow-up question: constexpr-correctness, compare and contrast with const-correctness :-) Comment on GotW #5 Solution: Overriding Virtual Functions by Herb Sutter
Yep, at least three times I had to stop myself from “fixing” that line to say auto pb = make_unique<derived>(); which would actually have resolved a few problems (or at least changed them) but wouldn’t have preserved the semantics of the question. To preserve the semantics, I stuck with unique_ptr<base> pb = make_unique<derived>(); However, I was actually _this_ close to applying the style I currently prefer of “auto var = Type{ expr };” for conversions, which in this case would be only very slightly more wordy auto pb = unique_ptr<base>{ make_unique<derived>() }; I held back mainly because that style is still unusual to most people’s eyes and seeing the unique_ptr and the make_unique strung that close together might take some getting used to for readers… but now that I look at it, it does have the advantage of being very nice and explicit about what’s going on! Hmm. The more I look at it, the more I’m liking it… Read More »Comment on GotW #6a: Const-Correctness, Part 1 by Nicol Bolas
> What is a "shared variable"? It’s an English phrase that has no well-defined meaning without some form of context. The first word, “shared” means to allow ownership between multiple parties. The word “variable” refers to the well-defined C++ concept of a variable. Thus the term would represent a variable that is in some way owned by multiple parties. The term “shared variable” is not defined by any version of ISO/IEC 14882 Standard for Programming Language C++. Nor is it a term in common, colloquial usage among C++ programmers. Therefore, I submit that the term cannot be considered to have a firm definition outside of what the words themselves mean. As such, it means nothing without further context. What are the multiple parties in question who might have ownership of the variable? What kind of ownership is under discussion? Furthermore, I would submit that it is not appropriate for Herb to unilaterally declare that this phrase has *any* particular meaning. It’s bad enough that we’ve got Scott Meyers inventing non-standard terms like “Universal References” that ultimately serve to drive them away from proper standard language. We don’t need multiple high-profile C++ people making it difficult for people to effectively communicate by unilaterally inventing terminology for concepts ex nihilo. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Lachlan Brad Easton
Yeah it was mentioned in an earlier post that C++14 would be targeted. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by GeoffW
I don’t mean to be picky (well, maybe I do), but is “uses for final are rarer” the most that can be said for “final”? On seeing the original JG question I had sort of hoped for more (the question did ask: “Why are they useful?”). Maybe something about the sort of design situations that it was intended to aid – it must have been introduced into the standard for a reason. Read More »Comment on GotW #4 Solution: Class Mechanics by decourse
@Herb, I guess what I’m after here is some advice as to what passing an object by value actually means. We all know by now the difference between passing a smart pointer and passing a raw pointer. In each case, choosing one over the other signals a clear intention about the interface. I the signature asks for a smart pointer, for example, it “means” that the function wants to manage the lifetime of the passed object, but if it asks for a raw pointer, that “means” it doesn’t. It’s a similar story with lvalue references and rvalue references. Moreover, these differences are part of the interface. I don’t really know what it means when a function asks a caller to pass an object by value. But whatever it means, it’s not really part of the interface, but part of the implementation. I don’t like that. It smells wrong. Read More »Comment on GotW #6a: Const-Correctness, Part 1 by Jesse Good
Hans Boehm uses the term “shared variable” throughout all his papers. However, he fails to give a formal definition as far as I can tell. The “Dictionary of Computer Science, Engineering and Technology” defines it as follows: Since we don’t have a formal definition of “shared variable”, the only question left Comment on GotW #6a: Const-Correctness, Part 1 by pip010 (@ppetrovdotnet)
this is confusing. does use semantics change and if no, why care? Read More »Comment on GotW #6a: Const-Correctness, Part 1 by Gregory
I’m a bit lost trying to put the change of meaning of const into the bigger picture. So, let me ask two counter-questions. 1) You have a simple struct And function that takes struct A by const-reference.
Without any assumptions, is it legal to put parameter a into standard container? 2) You have following class: class IntRef IntRef(const IntRef& other):ptr(other.ptr) void increment() const Is it safe to put object of this class into standard container? Read More »Comment on GotW #5: Overriding Virtual Functions by pip010 (@ppetrovdotnet)
few quick ones: 2) how exactly in this case: auto will default to base type and not derive type. cause I expect to have the same effect as invoking a virtual call on base* and derive*, which has different outcome as we all know. 3) about final , is the first time i hear about it. hope is not same semantic as in C#, though it looks like it is. Comment on GotW #5 Solution: Overriding Virtual Functions by Overloading base method in derived class | BlogoSfera
[…] I was playing with C# to see if it matched C++ behavior from this post: http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/ when I came across this very strange […] Read More »Comment on GotW #3 Solution: Using the Standard Library (or, Temporaries Revisited) by Sorting Localized Strings | Khuram Ali
[…] GotW #3 Solution: Using the Standard Library (or, Temporaries Revisited) (herbsutter.com) […] Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Johan Oudinet
I vote for auto pb = unique_ptr<base>{ make_unique<derived>() }; I also like the improvement in both being conformed to the style of using auto as much as possible and seeing, in a more obvious way, the “conversion” from derived to base. Comment on GotW #6a: Const-Correctness, Part 1 by mttpd
Regarding the definition of a shared variable — perhaps Section 1.2.5, “Data Terminology,” of the latest (draft) OpenMP specification can serve as an inspiration (together with providing a neat distinction between a “shared variable” and a “private variable”): http://www.openmp.org/mp-documents/OpenMP_4.0_RC2.pdf Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Mike
Guideline: Avoid default arguments on virtual functions in general. This needs to be more than just a guideline. It needs to be a _rule_. It’s just never a good idea. This is why function overloading exists. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Herb Sutter
@GeoffW: Re "uses of final are rarer" – well, they sort of are. I don't know of many, and during standardization Bjarne repeatedly asked for examples of problems it solved and patterns where it should be used, and I don't recall any major ones that stood out. The only one I know of offhand is that if you're defining a library module (which isn't a Standard concept yet) then making leaf classes final can give the compiler more information to devirtualize calls because of knowing code outside the library won't further derive, but I'm not sure how important that is these days in the presence of whole program optimization including aggressive devirtualization. @Johan: Okay, you guys are convincing me that maybe I’m worrying too much about acceptance of ‘auto everywhere.’ The reason I worried is because it’s a lightning rod issue that takes an amazing amount of energy in most C++11 overview sessions. Even on this blog when I announced I was restarting GotW and XC++, NEARLY EVERY comment on Reddit was about auto, which was mentioned only once in passing deep in the middle of the post. That’s all they could talk about. So I was leaning toward easing people into it, with a view of “you really need to get used to using auto frequently or at least consider it” while trying to avoid a brusque “this is the new way, get over it”… but okay, I’ve gone ahead with this change. Thanks for the feedback. Read More »Comment on GotW #6a: Const-Correctness, Part 1 by mordachaiwolf
1. What is a "shared variable"? Any variable that has a scope larger than a “single user” — to me that means it can be a class member or a global variable or a variable that has shared ownership amongst multiple points of access in a program even for a single threaded application. Any variable that has scope that crosses multiple threads is even more “shared” than that. 2. What do const and mutable mean on shared variables? `const` acts as a contract between provider and client. Declaring that something is a const parameter to a function, tells the clients of that API that the object that they’re handing over will not be used in any but a const manner (i.e. read-only or its const-member-functions employed). Casting around the interface you’re providing or using is almost certainly wrong – it violates the contract – and at that point you’re asking for the code to break — if not today, then in the future during maintenance. `mutable` means “internally modifiable under const contract conditions.” i.e. for a class A with mutable int b, b can be modified by any of A’s const member functions. It is not a violation of A’s const interface to modify mutable member b. I’ve used this commonly to cache values for a class – things that do not affect the state or meaning of A, but only help A do it’s job. e.g. if we have a class that represents a Filename, then I might have mutable members for volume, path, name, extension. As long as the filename as a whole doesn’t change semantics, those members can be updated at the pleasure of Filename – even in via its const APIs. Now that we’re dealing with multiple threads, mutable is useful to specify on the synchronization object if it is a member. Whether the internal state of my object is locked or not doesn’t change the semantics of it. So the const interface can remain coherent while internally I take a read-lock and do whatever I need to in order to execute the API-contract for my client. 3. How are const and mutable different in C++98 and C++11? ??? Read More »Comment on GotW #2 Solution: Temporary Objects by Thomas Gahr
@GeoffW: I don’t think sizeof(void*) std::string is doable no matter if you use SSO or COW – if we take COW, you’ll need one pointer for the data and one pointer for the reference count (or linked list, whichever you prefer) at least. You’ll also want to store the size of the string or you’re back to ::strlen for implementing .size(). If you take the “dumb” implementation of a string without any optimization – always allocate and memcpy data – you’ll need the data-pointer and the size member so you’re at 2*sizeof(void*) at least. Or am I wrong? Comment on GotW #2 Solution: Temporary Objects by Thomas Gahr
@GeoffW: FWIW: as far as I can see counter-COW argument boils down to exception safety since now any non-const access to the string (like operator[]) can throw std::bad_alloc as it mandates a deep copy of the data. I know your question was mainly about SSO, I just wanted to complete my last comment. Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Caleb Huitt
@Simon, @Arthur, and @Herb: You are all correct that I missed the slight change in semantics. For the learning purposes, then, I like Herb’s modified line, because it is more explicit about what is happening as well as a) reinforcing that auto should be used for things like this, and b) points out that a conversion is happening. I admit my eyes glazed over the first template specification, assuming a compatible result with make_unique. If I was actually reviewing a similar line in code, I’d expect auto to be used (or possibly to be assigned to a class member variable, which opens up different typing considerations). Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Arne Mertz
On the pb->f(1.0); you stress that overload resolution is done on the static type. I think the more surprising part for at least some people will be that having declared f virtual has no effect on the result because as you stated earlier f is not overridden but only hidden in derived , so the virtual function dispatch will still call base::f(double) . Read More »Comment on GotW #5 Solution: Overriding Virtual Functions by Arne Mertz
Yuck! That looks messed up, seems I’m too used to SO. Are there in-line code tags for comments like in the blog post itself? Read More » | ||||
| ||||
Thursday, May 23, 2013
FeedaMail: Comments for Sutterâs Mill
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment