Thursday, January 2, 2014

FeedaMail: Comments for Sutter̢۪s Mill

feedamail.com Comments for Sutter's Mill

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by Ralph Tandetzky

I just looked at the next question and figured out that it asks for what I already noticed. Sorry, I should have read on first. But here’s one more note: If both A and B inherit virtually from a common base (directly or indirectly) then the above change might not be as trivial. However, this is highly unlikely since B doesn’t have any virtual functions.

Read More »

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by Ralph Tandetzky

You can still remove one more header which is b.h . Just let the pimpl class X::impl inherit publicly from B and remove B as a private base of X . This would even work perfectly fine, if B had virtual functions which is excluded in the exercise.

Read More »

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by Herb Sutter

@Marcelo: using namespace std; is perfectly fine (and should be encouraged) in an implementation file after all #includes. See C++ Coding Standards Item 59: “Don’t write namespace usings in a header file or before an #include.”

However, you’re right that saying “std::” in front of the list member is now redundant. Removed, with credit. Thanks!

Read More »

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by Marcelo Pinto

Shouldn’t the standard headers come after our own header to avoid hiding some including errors in our own headers?

And in the last code snippet you have “using namespace std” (that I don’t like very much) and then you have “std::list…”. Don’t you think you should avoid “using namespace std” in such a short code?

Best regards

Read More »

Comment on GotW #7c: Minimizing Compile-Time Dependencies, Part 3 by Roman M.

Hello Herb,
in my experience, using your advice at the current language state in large projects is unfortunately utopical and rarely pays off:

- dependency rules are often not obvious, so a conservative developer will rather include too much instead of risking a broken build;
- we have to sacrifice performance for a compile-time issue which has arguably zero customer value;
- we have absolutely _no_ tool support, so a developer have to _guess_ which header has greatest impact and is worth her time;
- even if some issues were somehow located and fixed using PIMPL, a regression is just a matter of time;
- templates make sutuation much worse;

Some time ago I’ve create an issue on User-Voice (http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2680137-make-header-include-refactoring-possible). I understand that creating good solution for compile-time issues is far from trivial, but currently I would probably invest in better hardware instead of wasting my time on PIMPL

Read More »

Comment on GotW #7c: Minimizing Compile-Time Dependencies, Part 3 by Phil Nash

@Herb. This is not a response to your questions, but is pertinent to the topic.

I’ve been following this series with interest to see if I can pick up any more tips in my war against build-time sapping dependencies. While it’s all been good stuff and covered well I’ve not seen anything new – yet I still suffer from productivity killing compile times in several projects I’m working on (to be clear, these are mostly legacy code bases where it’s too late for the large scale refactoring necessary to take advantage of some of these techniques on enough of the code-base – or the runtime cost is too high – e.g. with the pImpl idiom).
We’ve had some success with pre-compiled headers – but also constantly have problems with them (VS2008 – has it finally got any better in more recent incarnations?).

In the first post you alluded to modules – which I think should be a huge win in this area. But when I asked Bjarne about it earlier this year he seemed to think they weren’t even on the radar for C++17 at this point. Is that still the case? Can you give any more insight here? Will you really be covering it in an upcoming post?

Read More »

Comment on GotW #7c: Minimizing Compile-Time Dependencies, Part 3 by Phil Nash

@Matthieu (& @herb) the fixed sized block of storage with placement new (and explicit destructor) is the usual solution. As Herb says adding a bit of extra headroom is usually a good idea.
Another good idea is to put a static assert in the implementation to make sure the compiler tells you if that size ever becomes too small.

However, it may also be worth considering using a pool allocator, or some other more efficient allocator (I’ve found tbb’s scalable_allocator to be a very good general purpose allocator) to keep the size dynamic (and thus always correct), but with a much smaller overhead. You can’t beat the near zero overhead of the obtrusive storage block but a decent allocator may be good enough for a lot of cases where the std allocator isn’t.

Read More »

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by Mike Capp

Given that pimpl introduces an allocation anyway, I’ve never really seen what benefits it offers that couldn’t be provided more cleanly and flexibly by a factory returning a unique_ptr to a (probably abstract) base class. Pimpl trades vtable indirection for data-access indirection, which isn’t an obvious win, and makes subclassing a good deal uglier since you need to subclass both handle and body types.

Could you expand on where you see the relative merits here?

Read More »

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by Ralph Tandetzky

@Mike: For polymorphic classes your approach is an alternative. But for value classes (types being copyable and movable) a base class could introduce slicing problems. Instead of copying you would have to clone your value type. Hence normal copy semantics are impossible because of this implementation detail. The idea is to preserve the semantics of the class and only touch the internals in the private section of the class. Even in the case of a class hierarchy pimpling is sometimes preferred since it’s less code to write. Think about it: You have to create an interface class and mirror the functions there in the implementation class. This is not necessary when pimpling and only those functions are virtual which really need to be virtual giving the reader of your code an idea of intent. He or she can then know which functions may be customized.

Read More »

Comment on GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2 by nosenseetal

@herb:
“Note that not only does the move-only unique_ptr member disable compiler-generated copying by default, but the explicitly user-declared destructor also disables compiler-generated move by default. Thanks for the note!”
I had no idea about this, if you dont consider it way tooo basic for gotw maybe you could write about that. also since it is 2014 if i could have one wish it is gotw on emplace_back vs push_back(for vector, i guess same conclusions apply to the other containers)

Read More »

Comment on GotW #7c: Minimizing Compile-Time Dependencies, Part 3 by germinolegrand

1) Inheritance is the tightest coupling you can ever find in C++ (inheritance with virtual overriding really is the most complicated dependency to hide).
The sencond-tightest is membership. But you already talked about it in part #7b, we can get rid of it with pimpl idiom if it’s private.

These are the ones that determine the size of the class, which is what the compiler always need. Interestingly, these also are the ones that can’t be recursive, thus it makes it a solvable problem (no cyclic inclusion) without any indirection.

2) The private inheritance to class B, that has no virtual functions, can be transformed into a private member. It has no consequence on the size, unless sizeof B is zero (as a member it is required to be at least 1 if i make no mistake). Anyway, if it is private member, it can become a member of the pimpl and simply disappear from class X.

Another way of having class B disappear from class X, but keeping inheriting from class B (perhaps to access some protected things, or to keep its zero size), is to simply make struct impl publicly inherit from class B (so that it can be accessed from class X, but needing some proxy functions in struct impl to access the protected part of class B).

Once any of those two solutions are applied, the #include “B.h” can be removed from x.h and added in x.cpp.

It’s worth mentionning that the order in which class X inherits from class A then from class B permits to preserve construction order while sending class B to the pimpl. If class B really needed to be constructed before (or deleted after) class A, this wouldn’t be possible. It’s so easy to mess up the construction/destruction order by playing with dependancies.

The code for x.h now looks like this (a forward-declaration to class B is needed for the f function):

  //  x.h: after converting to use a Pimpl to hide implementation details  //  #include <iosfwd>  #include <memory>  #include "a.h"  // class A (has virtual functions)  class B;  class C;  class E;    class X : public A {  public:         X( const C& );      B  f( int, char* );      C  f( int, C );      C& g( B );      E  h( E );      virtual std::ostream& print( std::ostream& ) const;    private:      struct impl;      std::unique_ptr<impl> pimpl;   // ptr to a forward-declared class  };    std::ostream& operator<<( std::ostream& os, const X& x ) {      return x.print(os);  }  

and the x.cpp like that :

  //  Implementation file x.cpp  //  #include <list>  #include "b.h"  // class B (has no virtual functions)  #include "c.h"  // class C  #include "d.h"  // class D  using namespace std;    struct X::impl: public B {      std::list<C> clist;      D            d;  };    X::X() : pimpl{ make_unique<X::impl>(/*...*/) } { }  X::~X() =default;  

The last trick is not needed in the GotW question, but might be interesting. What if class B had virtual functions overrided in class X ? The solution may have an extra cost, with crossed dependancies between class X and struct impl.

First, the inheritance is changed, same as before, instead of class X, struct impl will inherit from class B. The overriding functions will be located in struct impl.

Then, everything depends on what is in the overriding functions. If the scope of struct impl is enough to implement them (for example it only needs to play with the members of the pimpl idiom), all is fine, nothing to do, no extra cost.

On the contrary, if it needs some access to class A or class X (eg. call a function in the (virtual) interface, or access to a member not in struct impl), there will come the necessary dependancy to class X. An extra member of impl will have to be added : a reference to an X (the X constructor will pass *this to the impl constructor). If needed, class X will be added a friend class impl; declaration so that class impl can access private things of class X it needs.

One of the drawbacks (not often a problem) is that a reference to a B can no longer be dynamicly casted into a reference to an A or an X.

I wish you all a happy new year =).

Read More »
 
Delievered to you by Feedamail.
Unsubscribe