Wednesday, January 1, 2014

FeedaMail: Comments for Sutter’s Mill

feedamail.com Comments for Sutter's Mill

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

Hi Herb, this is a great topic. I’ve submitted a proposal to further reduce compile times and increase encapsulation by allowing the programmer to define additional non-virtual private methods outside of class scope. It’s an artificial limit that just makes class design less flexible and requires unnecessary recompilation.

https://github.com/fmatthew5876/stdcxx-privext

Do you have any opinion about this idea?

Read More »

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

Herb I guess you dont take wishlist requirements since you are not Santa, but it would be nice if VC++ compiler would support pimpl switch so people dont need to rewrite their code for daily hackery :) but still get the productivity boost and still get the perf in release mode without pimpling :) .

Read More »

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

1. Inheritance.
2. X::impl could inherit from B, in the cpp file, which would allow us to move #include “b.h” in the cpp file.
This is because B is not part of the public interface, so it’s an implementation detail, AND it don’t have virtual functions, which is a kind of externally available interface.
For the same reasons, we can’t remove A from the interface so it’s include needs to stay here.

Read More »

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

JG: Friendship is the tightest coupling, followed by inheritance; thus the guideline, prefer composition over inheritance.

Guru: Given the big clue (read the comments) and the previous appetizer, it seems obvious that X need not inherit from B. Since we are already using PIMPL, all uses of B should thus move to the source file and therefore the include of B can be removed. B will still need to be forward declared since it is mentioned in the interface.

Question: I see here the use of unique_ptr, which requires a separate allocation. I have wondered a couple times how to get rid of this separate allocation (it slows down the construction and hurts cache friendliness) and I could only come up with the use of aligned_storage for a raw block of memory (of predetermined size) in X. However the need to suitably size this block implies the issue of ABI breakage if the size need ever change, so this is less stable ABI wise (but still insulates the client from most headers). Any thoughts ?

Read More »

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

In the requirements for #3 you say:
* any current code that already uses X should not be affected beyond requiring a simple recompilation.

However introducing a unique_ptr into X means that X no longer has value semantics, its copy constructor (as well as operator=) are disabled, this may affect current code that uses X

Read More »

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

@Motti: I did mention earlier in the article that “If copy and move are appropriate for your type, write those four operations to perform a deep copy that clones the impl state.” but I agree it bears repeating. I’ve added an extra paragraph and an extra comment line in the code. 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!

Read More »

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

@Matthieu: Yes, that’s basically what you’d need to do to avoid the allocation overhead in Pimpl — have a block of storage in the class of sufficient size, perhaps with extra space so that you can add some extra members in the future without causing an ABI breakage or recompilation.

Read More »

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

1) I think tightest coupling in cpp is friendship(it gives private members access to non related class/methods). Inheritance is second.

2) Relationship with B can be moved to impl, since B has no virtual functions and it’s private base class of X.
This modification doesn’t change public interface of X.

  //x.h    #include "a.h"  // class A (has virtual functions)  class B;  // class B (has no virtual functions) - forward declared  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 );      ~X();      virtual std::ostream& print( std::ostream& ) const;    private:      struct impl;      std::unique_ptr<impl> pimpl;   // ptr to a forward-declared class  };  
  //x.cpp  #include "b.h"  struct X::impl: public B{      /* ... */  }  X::X( const C& ) : pimpl{ make_unique<X::impl>(/*...*/) } { }  X::~X() = default;    

After changes all calls of B methods in X should be redirected to impl.
To make it work B should be public base of X::impl. If B has protected members, such calls should be enclosed by public functions to allow access from X. Another way to do it is to add friendship between X::impl and X (B can remain private base of X::impl).

Read More »
 
Delievered to you by Feedamail.
Unsubscribe

No comments:

Post a Comment