1. Abstract
Add a class template,indirect_value , to the C++ Standard Library to support free-store-allocated objects with value-like semantics. 
   2. Introduction
The class template,indirect_value , confers value-like semantics on a free-store-allocated object. An indirect_value  may hold an object of a class T, copying the indirect_value  will copy the object T , and const ness will propagate from the owning classes to the indirect_value  type. 
   2.1. Motivation - a perfect PImpl
In C++, when anything in a class definition changes, dependent classes require recompilation. As early as 1992 the Handle/Body idiom was suggested to break this dependency [J. Coplien]. From this pattern, the PImpl idiom was specialised [H. Sutter]. Almost three decades on since these ideas started circulating implementation of the PImpl idiom requires thought about implementation details around copying and to support this feature requires user intervention.For convenience, the widget class will be referred to as the “visible class” and impl class the “// Header file class widget { public : widget (); ~ widget (); private : class impl ; std :: unique_ptr < impl > pimpl_ ; }; // Implementation file class widget :: impl { // ::: }; widget :: widget () : pimpl_ { std :: make_unique < impl > ( /*...*/ } { } widget ::~ widget () = default ; 
PImpl  class”. Note, semantically the PImpl  class is the implementation details of the visible class. 
   2.1.1. Issues with unique_ptr < impl >  implementation of PImpl Idiom
   2.1.1.1. const-propagation
Using  to store the implementation object introduces an issue - within a -qualified
 member function, an instance of the visible class can mutate data inside the implementation object.  This is because  qualification applies only to the  value, and not the pointed-to-object.
The compiler is unable to give thread-compatibility guarantees for  objects when  is not propagate:  does not mean immutable in the face of pointer-like-member data.
The desired semantics of a PImpl-owner are value-like, like those of  which has appropriate  and non--qualified overloads for  and .
2.1.1.2. copies
The copy-constructor and copy-assignment operator ofstd :: unique_ptr  are deleted. Users of a class with a std :: unique_ptr  member will be required to implement copy-construction and copy-assignment.  Implementation of these methods for a class with PImpl members is non-trivial [S. Meyers]. 
   2.1.2. Issues with polymorphic_value < impl >  implementation of PImpl Idiom
    The class template polymorphic_value  confers value-like semantics on a free-store-allocated object. This satisfies our requirement for const-propagation and a compiler generated copy constructor and copy assignment operator but incurs an additional cost in supporting polymorphism.
To implement deep copies of subclasses, polymorphic_value  employs type-erasure which has run-time cost due to virtual dispatch and memory indirection. We do not need to support polymorphism for our PImpl object and should not pay for what we do not use. 
   2.1.3. Perfect Implementation of the PImpl Idiom
Likepolymorphic_value , indirect_value  confers value-like semantics on a free-store-allocated object. Unlike polymorphic_value , indirect_value  does not support polymorphism - indirect_value < T >  is either empty or contains an object of type T . 
// Header file class widget { public : widget (); widget ( widget && rhs ) noexcept ; widget ( const widget & rhs ); widget & operator = ( widget && rhs ) noexcept ; widget & operator = ( const widget & rhs ); ~ widget (); private : class impl ; std :: indirect_value < impl >> pimpl ; }; // Implementation file class widget :: impl { // ::: }; // Force instantiation of the rule of zero methods in the translation unit where implementation details are known. widget :: widget ( widget && rhs ) noexcept = default ; widget :: widget ( const widget & rhs ) = default ; widget & widget :: operator = ( widget && rhs ) noexcept = default ; widget & widget :: operator = ( const widget & rhs ) = default ; widget ::~ widget () = default ; 
Now the visible class has compiler-generated copy and move constructors, copy and move assignment operators and destructor. All of these compiler-generated functions will behave correctly.
2.2. Prior Art
There have been previous proposal for deep-copying smart pointers that proposed copy semantics [W. Brown].cloned_ptr  was proposed in [J. Coe], however under guidance of LEWG this was renamed to polymorphic_value .  With this change in name came the addition of const propagation. 
   This paper is not unique in these ideas. GitHub code search finds 602k lines of code referencing "PImpl" and 99 C++ repositories claiming to provide generic implementations of Pimpl. Additionally other authors have addressed this topic [A. Upadyshev].
2.3. Completeness of T*
Recommended practice for pointer-to-implementation of PImpl classes since C++11 has been to store the pointer-to-implementation in a std::unique_ptr [S. Meyers]. Smart pointer types in the Standard Library expect that some of the members can be instantiated with incomplete types [H.Hinnant]. Similarly, this is the case forindirect_value , the table outlines the expected behaviour for incomplete pointer types: 
   | Method | Description | Incomplete/Complete | 
|---|---|---|
       | Default constructor | Incomplete | 
       | Copy-constructor | Complete | 
       | Move-constructor | Incomplete | 
       | Destructor | Complete | 
       | Copy-assignment | Complete | 
       | Move-assignment | Complete | 
       | Indirection-operator | Incomplete | 
       | Indirection-operator | Incomplete | 
       | Member-of-pointer-operator | Incomplete | 
       | Member-of-pointer-operator | Incomplete | 
       | Bool-operator | Incomplete | 
       | Swap | Incomplete | 
2.4. Impact on the standard
This proposal is a pure library extension. It requires additions to be made to the standard library header< memory > . 
   3. Technical specifications
3.1. X.X Class template default_copy  [default.copy]
The class template default_copy serves as the default copier for the class templatenamespace std { template < class T > struct default_copy { T * operator ()( const T & t ) const ; }; } // namespace std 
indirect_value .
The template parameter T  of default_copy  may be an incomplete type. 
   - 
     
Returns:
new T ( t );  
3.2. X.Y Class template indirect_value  [indirect_value]
   3.2.1. X.Y.1 Class template indirect_value  general [indirect_value.general]
    An indirect_value  is an object that owns another object and manages that other object through a pointer. More precisely, an indirect value is an object v  that stores a pointer to a second object p  and will dispose of p  when v  is itself destroyed (e.g., when leaving block scope (9.7)). In this context, v  is said to own p . 
   An  object is empty if it does not own a pointer.
Copying a non-empty  will copy the owned object so that the copied  will have its own unique copy of the owned object.
Copying from an empty  produces another empty .
Copying and disposal of the owned object can be customised by supplying a copier and deleter.
The template parameter  of  must be a non-union class type.
The template parameter  of  may be an incomplete type.
[Note: Implementations are encouraged to avoid the use of dynamic memory for ownership of small objects.]
3.2.2. X.Y.2 Class template indirect_value  synopsis [indirect_value.synopsis]
template < class T , class C = std :: default_copy < T > , class D = std :: default_delete < T >> class indirect_value { public : using value_type = T ; // Constructors constexpr indirect_value () noexcept ; explicit indirect_value ( T * p , C c = C {}, D d = D {}); indirect_value ( const indirect_value & p ); indirect_value ( indirect_value && p ) noexcept ; template < class ...Ts > indirect_value ( std :: in_place_t , Ts && ... ts ); // Destructor ~ indirect_value (); // Assignment indirect_value & operator = ( const indirect_value & p ); indirect_value & operator = ( indirect_value && p ) noexcept ; // Modifiers void swap ( indirect_value < T >& p ) noexcept ; // Observers T & operator * (); T * operator -> (); const T & operator * () const ; const T * operator -> () const ; explicit operator bool () const noexcept ; }; // indirect_value creation template < class T , class ...Ts > indirect_value < T > make_indirect_value ( Ts && ... ts ); // indirect_value specialized algorithms template < class T > void swap ( indirect_value < T >& p , indirect_value < T >& u ) noexcept ; } // end namespace std 
3.2.3. X.Y.3 Class template indirect_value  constructors [indirect_value.ctor]
   - 
     
Remarks: The method shall work with incomplete pointer type for
.T  - 
     
Effects: Constructs an empty
.indirect_value - 
       
Postconditions:
.bool ( * this ) == false 
 - 
       
 
- 
     
Effects: Creates an
object that owns the pointerindirect_value . Ifp is non-null then the copier and deleter of thep constructed are moved fromindirect_value andc .d  - 
     
Requires:
andC satisfy the requirements of CopyConstructible. IfD is non-null then the expressionp returns an object of typec ( * p ) . The expressionT * is well-formed, has well-defined behaviour, and does not throw exceptions.d ( p )  - 
     
Postconditions:
.bool ( * this ) == bool ( p )  - 
     
Remarks: A custom copier and deleter are said to be ‘present’ in a
initialised with this constructor.indirect_value  
- 
     
Constraints:
is_copy_constructible_v < T >  - 
     
Effects: Creates a
object that owns a copy of the object managed byindirect_value . The copy is created by the copier inp . Ifp has a custom copier and deleter then the custom copier and deleter of thep constructed are copied from those inindirect_value .p  - 
     
Throws: Any exception thrown by the copier or
if required storage cannot be obtained.bad_alloc  - 
     
Postconditions:
.bool ( * this ) == bool ( p )  
- 
     
Effects: Move-constructs an
instance fromindirect_value . Ifp has a custom copier and deleter then the copier and deleter of thep constructed are the same as those inindirect_value .p  - 
     
Postconditions:
contains the old value of* this .p is empty.p  - 
     
Remarks: The method shall work with incomplete pointer type for
.T  
- 
     
Effects: Constructs an
which owns an object of typeindirect_value direct-non-list-initialized withT std :: forward < Ts > ( ts )...  - 
     
Throws: Any exception thrown by the selected constructor of
orT if required storage cannot be obtained.bad_alloc  
3.2.4. X.Y.4 Class template indirect_value  destructor [indirect_value.dtor]
    ~ indirect_value ();  
   - 
     
Effects: If
there are no effects. If a custom deleterget () == nullptr is present thend is called and the copier and deleter are destroyed. Otherwise the destructor of the managed object is called.d ( p )  
3.2.5. X.Y.5 Class template indirect_value  assignment [indirect_value.assignment]
    indirect_value &  operator = ( const  indirect_value &  p );  
   - 
     
Constraints:
is_copy_assignable < T >  - 
     
Effects:
owns a copy of the resource managed by* this . Ifp has a custom copier and deleter then the copy is created by the copier inp , and the copier and deleter ofp are copied from those in* this . Otherwise, the resource managed byp is initialised by the copy constructor of the resource managed by* this .p  - 
     
Throws: Any exception thrown by the copier or
if required storage cannot be obtained.bad_alloc  - 
     
Returns:
.* this  - 
     
Postconditions:
.bool ( * this ) == bool ( p )  
- 
     
Effects: Ownership of the resource managed by
is transferred to this. Ifp has a custom copier and deleter then the copier and deleter ofp is the same as those in* this .p  - 
     
Returns:
.* this  - 
     
Postconditions:
contains the old value of* this .p is empty.p  
3.2.6. X.Y.6 Class template indirect_value  modifiers [indirect_value.modifiers]
    void  swap ( indirect_value &  p )  noexcept ;  
   - 
     
Effects: Exchanges the contents of
andp .* this  - 
     
Remarks: The method shall work with incomplete pointer type for
.T  
3.2.7. X.Y.7 Class template indirect_value  observers [indirect_value.observers]
T & operator * (); const T & operator * () const ; 
- 
     
Requires:
.bool ( * this )  - 
     
Returns: A reference to the owned object.
 
T * operator -> () noexcept ; const T * operator -> () const noexcept ; 
- 
     
Requires:
.bool ( * this )  - 
     
Returns: A pointer to the owned object.
 - 
     
Remarks: The method shall work with incomplete pointer type for
.T  
- 
     
Returns: false if the
is empty, otherwise true.indirect_value  - 
     
Remarks: The method shall work with incomplete pointer type for
.T  
3.2.8. X.Z.8 Class template indirect_value  creation [indirect_value.creation]
template < class T , class U = T , class ...Ts > indirect_value < T > make_indirect_value ( Ts && ... ts ); 
- 
     
Constraints:
is true.is_constructible_v < U , Ts ... >  - 
     
Expects:
meets theU requirements.Cpp17CopyConstructible  - 
     
Returns: A
owning an object of type direct-non-list-initialized withindirect_value < T > .std :: forward < Ts > ( ts )...  
4. Acknowledgements
The authors would like to thank Thomas Russell, and Andrew Bennieston for useful discussions on the topic and the BSI panel for on-going support.5. References
[J. Coe] p0201r3: A polymorphic value-type for C++
[J. Coplien] Advanced C++ Programming Styles and Idioms (Addison-Wesley), James O. Coplien, 1992
[A. Upadyshev] PIMPL, Rule of Zero and Scott Meyers, Andrey Upadyshev, 2015
[H. Hinnant] “Incomplete types and shared_ptr / unique_ptr”, Howard Hinnant, 2011
[H. Sutter] "Pimpls - Beauty Marks You Can Depend On", Herb Sutter, 1998
[Impl] Reference implementation: indirect_value, J.B.Coe
[S. Meyers] Effective Modern C++, Item 22: When using the Pimpl Idiom, define special member functions in the implementation file, Scott Meyers, 2014
[W. Brown] n3339: A Preliminary Proposal for a Deep-Copying Smart Pointer, Walter E. Brown, 2012