Saturday, April 24, 2010

private_ptr: A friend smart pointer to access private members

Friend can be used to access the internals of a class for unitary test purposes. We can define an smart pointer private_ptr template class and a private_cast template function, which gives a private access to a class in the same way const_cast grant non const access.
// private_ptr.h
template <typename Concept> 
class private_ptr {
  private_ptr(Concept & c) : c_(c) {}
  Concept * operator->() {
    return &c_;
  }
  const Concept* operator->() const {
    return &c_;
  }
};
template <typename Concept> 
private_ptr> private_cast(Concept& c) {
    return private_ptr(c);
}
A class can grant friend access to the private pointer class in a controlled way,  e.g. unit tests access to the private members,  as follows:

#include <private_ptr.hpp>
class C {
#ifdef C_UNIT_TEST
    friend class private_ptr<C>;
#endif
    // ...
};
As the friend class is defined only if C_UNIT_TEST is defined, there is no risk that application code uses this back-door access. The unit test code can access private members as follows:

#include <C.hpp>
void test_private()
{
  // ...
  C c;
  private_cast(c)->private_op();
  assert(private_cast(c)->private_field==0);
  //...
}

Unfortunately this smart pointer can not be used to access private types.

Monday, April 19, 2010

Extrinsic Conversions

I've needed recently to convert from chrono::time_point to posix_time::ptime and from chrono::duration to posix_time::time_duration.
This kind of conversions are needed quite often when you use code from two different libraries that have implemented the same concept using of course different representations and have hard coded the library interface to its own implementation. Well this is a normal situation we can't avoid. Life is life.
Quite often we need to convert unrelated types Source and Target. As these classes are unrelated, neither of them offers conversion operators to the other. Usually we get it by defining a specific function such as
Target ConvertToTarget(Source& v);
In my case I started by defining
template <typename Rep, typename Period>
boost::posix_time::time_duration
convert_to_posix_time_time_duration(
  const boost::chrono::duration<Rep, Period>& from);

template <typename Clock, typename Duration>
posix_time::ptime
convert_to_posix_time_ptime(
  const chrono::time_point<Clock, Duration>& from);
Imagine now that you need to convert a std::pair<Source, Source> to a std::pair<Target, Target>. The standard defines conversions of pairs if the related types are C++ convertible:
template <typename T1, typename T2>
struct pair {
  ...
  template<class U, class V>
  //requires Constructible 
  // && Constructible
  std::pair(const pair<U, V>& p);

  template<class U , class V>
  //requires HasAssign 
  // && HasAssign
  std::pair& operator=(const std::pair<U , V>& p);
  ...
};
But as the types Target and Source are not C++ convertible other than using a specific function.
Well we can again define a specific function
std::pair<Target,Target>
ConvertToPairOfTarget(std::pair<Source,Source>& v)
{
  return std::make_pair(
  ConvertToTarget(v.fisrt),
  ConvertToTarget(v.second));
}
While the ConvertToTarget could be specific, the ConvertToPairOfTarget should be generic
template <typename Target1, typename Target2
, typename Source1, typename Source2>
std::pair<Target1,Target2>
ConvertToPair(std::pair<Source1,Source2>& v);

In order to do that we need that the pair template parameters define a common function, let it call convert_to
template <typename Target, typename Source>
Target convert_to(Source& v);
so ConvertToPair can be defined as

template <typename Target1, typename Target2,
typename Source1, typename Source2>
std::pair<Target1,Target2>
ConvertToPair(std::pair<Source1,Source2>& v)
{
  return std::make_pair(
  convert_to<Target1>(v.fisrt),
  convert_to<Target2>(v.second));
}
We need to specialize the convert_to function for the specific classes Source and Target. We can do it as follows
Target  convert_to(Source& v) {
  return ConvertToTarget(v);
}
So now I can convert std::pair<chrono::time_point<Clock, Duration>, boost::chrono::duration<Rep, Period> > to std::pair<boost::posix_time::ptime, boost::posix_time::time_duration> using the ConvertToPair function.
What about converting std::pair<Source,std::pair<Source,Source> > to std::pair<Target,std::pair<Target,Target> >? The issue now is that convert_to(std::make_pair<to, std::make_pair<to,to> >) do not compiles because the conversion of std::pair is named ConvertToPair. So we need to specialize the function convert_to for pairs.
template <typename T1, typename T2,
typename S1, typename S2>
static std::pair<T1,T2>
convert_to(std::pair<Source1,Source2>& from) {
{
  return std::pair<T1,T2>(
  convert_to<T1>(from.first),
  convert_to<T2>(from.second));
}
There is still a last point. The preceding design works well with unrelated classes, but what about classes that already define some kind of conversion, using a constructor or a conversion operator. Do we need to make specialization for these conversion? The answer is no. We need just to define the default implementation of convert_to function to just return the explicit conversion.
template < typename Target, typename Source>
Target convert_to(const Source& from)
{
  return Target(from);
}
Classes or algorithms relying on a conversion by copy-construction or by the conversion operator can be made more generic by relaying in a function that explicitly states this conversion. Thus, instead of requiring
Target(from)
requires
convert_to<Target>(from)
So one of the advantages of using this common functions is uniformity. The other is that now we are able to find all the explicit conversions to one type, as we can do with explicit casts.

C++ Evolution?
C++0x has added explicit conversion operators, but they must always be defined in the Source class. The same applies to the assignment operator, it must be defined on the Target class.
What it will interesting is to be able to add constructors and assignments operators to the class std::pair, so we can say that two pairs are convertible if the parameters are explicitly convertible using a convert_to function
template<class U , class V>
  //requires HasConvertTo 
  // && HasConvertTo
  std::pair& operator=(const std::pair<U , V>& p) {
  return std::make_pair(
  convert_to<T1>(p.first),
  convert_to<T2>(p.second));
}
But this is not currently possible, we can not add operations to a class.

Another possibility could be to make an evolution to the C++ standard, so the convertible concept takes care of extrinsic conversions. We could be able to implicitly or explicitly add extrinsic conversion operators between unrelated types.
template < typename To, typename From >
operator To(const From& val);
For example we could specialize the conversion from chrono::time_point to posix_time::ptime as follows
template < class Clock, class Duration>
operator boost::posix_time::ptime(
const boost::chrono::time_point<Clock, Duration>& from)
{
  using namespace boost;
  typedef chrono::time_point<Clock, Duration> time_point_t;
  typedef chrono::nanoseconds duration_t;
  typedef duration_t::rep rep_t;
  rep_t d = chrono::duration_cast<duration_t>(
  from.time_since_epoch()).count();
  rep_t sec = d/1000000000;
  rep_t nsec = d%1000000000;
  return  posix_time::from_time_t(0)+
    posix_time::seconds(static_cast<long>(sec))+
    posix_time::nanoseconds(nsec);
}

Tuesday, April 13, 2010

Backdoor C++ Idiom - part III

I will end this suite around the backdoor C++ idiom with implementation variants.

Implementation

Analyze applicability
First of all, the designer must be sure the pattern is applicable to the class by checking the applicability clauses.

Identify the part of the Component that must be used with caution and its protocol
This is a class specific task that must be done with caution. Only the actual safe operations must be public. Operations and data which are needed to open the interface and which must be used with caution by a safe adapter class should be private and usually annotated as such.
class  mutex {
public:
  // ... 
  typedef mutex_backdoor backdoor;
  friend class backdoor ;
  // list of predefined safe adapters
  typedef mutex_scoped_lock scoped_lock;
private: // backdoor 
  void  lock();// backdoor 
  void  unlock();// backdoor 
  // ... 
};
If the Component is a model of a Concept, which has already a backdoor through a template class and safe component adapters, use them.
class  mutex {
public:
  // ... 
  typedef backdoor<mutex> backdoor;
  friend class backdoor ;
  typedef scoped_lock<mutex> scoped_lock;
  // ... 
};
Safe guaranties: unlock must be called if lock is called, i.e. lock/unlock are well balanced.

Define a backdoor interface and safe guaranties for Component

This class gives you a back-door access to your class. There are at least two possibilities: by class instance or static
  • instance interface: an instance of a backdoor is initialized with an instance of the class, giving back-door access


  • static interface: this could be more efficient with compilers that haven't a good optimizer.
Instance interface
class  mutex_backdoor {
public:
  mutex_backdoor ( mutex & mtx) : mtx_(mtx) {}
  void lock() {
    mtx_.lock();
  }
  void unlock() {
    mtx_.unlock();
  }
private:
  mutex & mtx_;
};
The SafeAdapter client could write
mutex::backdoor(mtx).lock();

Static interface
struct mutex_backdoor {
  static void lock(mutex& mtx) {
    mtx.lock();
  }
  static void unlock(mutex& mtx) {
    mtx.unlock();
  }
};
The SafeAdapter client could write
mutex_backdoor::lock(mtx); 
 
When applying the idiom to generic programming, the backdoor should be applied to a concept. So, the backdoor for a mutex class can be a template class, which is the backdoor for models of the Lockable concept, and then the backdoor is written only once. For brevity purposes only the by instance class interface is shown:
template <typename Lockable>
class  backdoor {
  backdoor( Lockable & mtx) : mtx_(mtx) {}
  void lock() {
    mtx_.lock();
  }
  void unlock() {
    mtx_.unlock();
  }
private:
  Lockable& mtx_;
};
And the SafeAdapter client could write
backdoor<mutex>(mtx).lock();

The use of the backdoor template class can be simplified by using a backdoor generator function:
template <typename Lockable>
typename Lockable::backdoor backdoor_access( Lockable& mtx)
{
  return Lockable:: backdoor(mtx);
}
And the SafeAdapter client could write
backdoor_access(mtx).lock();

Define a set of Component Safe Adapters that provides a safe interface to your Component

This set of ComponentSafeAdapters must at least provide the same functionalities as the Component would provide if the interface of the backdoor were public in a safe way. For brevity purposes, only the generic safe component adapter accessing a per instance backdoor is shown:
 
// ensures that unlock is called on destruction when owned 
// note that this is different to ensure that the mutex is 
// locked during the lifetime of the scoped variable. 
template <typename Lockable>
class  scoped_lock {
public :
  scoped_lock( Lockable & mtx, bool owns=true) // [1] 
    : mtx_(mtx),
    , owned(false) {
    if (owns) lock();// [2] 
  }
  ~scoped_lock(mutex&) {
    if (owned) { // [5] 
      backdoor_access(mtx_).unlock();// [4] 
    }
  }
  void  lock() {
    if (!owned) { // [3] 
      backdoor_access(mtx_).lock();// [4] 
      owned = true; // [3] 
    } else {
      // ERROR // [6] 
    }
  }
  void  unlock() {
    if (owned) { // [3] 
      backdoor_access(mtx_).unlock();// [4] 
      owned = false; // [3] 
    } else {
      // ERROR // [6] 
    } 
  } 
 bool  owned() {
    return owned;
  }
private :
  bool owned;
  mutex& mtx_;
};
  1. The interface allows to lock the mutex on construction
  2. Use of an internal function
  3. The use of the lock/unlock is controlled by the owned variable
  4. Use of backdoor interface using the backdoor_access function.
  5. On destruction the mutex is unlocked if owned.
  6. Error has not been detailed.
Use the component and the Component Safe Adapters
The use of the ComponentSafeAdapter is obvious.
 
mutex guard;
{
  // guard.lock() compilation ERROR
  mutex::scoped_lock scoped( guard );
  // enter the critical section
  // ...
  // guard.unlock() compilation ERROR
}

Identify other Component Safe Adapters

Different Component Safe Adapters can be identified. Associated to the Lockable concept there are:
  • scoped_strict_lock: ensures that the mutex is owned during the lifetime of the scoped variable.
  • locking_ptr: this smart pointer locks the mutex when de-referencing the pointer, call the function, and then unlocks the mutex.
  • scoped_locking_ptr: this smart pointer locks the mutex on construction, defines the operator->, and unlocks the mutex on destruction.
  • scoped_reverse_lock: unlocks the mutex on construction, and locks the mutex on destruction. For recursive mutex, this do not implies that on the scoped block the mutex is unlocked.
The designer of such ComponentSafeAdapter must be aware of the possible interactions between the set of adapters, and must specify which are the guaranties. Next follows some interactions between ComponentSafeAdapters.
mutex guard;
void f()
{
  scoped_strict_lock strict( guard );
  // the mutex is locked 
  {
    // call to a self locked function 
    // this will work if the mutex is recursive 
    g();
    // pass a strict lock to a function. The “other” object has been 
    // constructed with an external locking mechanism and its correct 
    // behavior depends on the caller, which owns the mutex. 
    // Having a strict lock ensures this. 
    other.h(strict);
  }
  {
    // the user is aware that on this block the mutex must be unlocked but a strict guards is not a scoped_lock 
    scoped_reverse_lock reverse( strict ); // ERROR do not compile 
    // the mutex is unlocked 
    // ... 
    // the mutex is locked  
  }
  // the mutex is still locked 
  h( strict );
}
void g() {
scoped_lock scoped( guard );
  // mutex is locked 
  // ... 
  {
    scoped_reverse_lock reverse( scoped );
    // the mutex is unlocked 
    // ... 
    // the mutex is locked 
  }
  // mutex is locked 
  // ... 
} 
 
Know Uses
  • Boost::Threads library (v1. 34.1): The synchronization part of this library used the backdoor for the model of the Lockable concept with a static interface (lock_ops) defined on a nested namespace named ‘detail'. It is admitted that the ‘detail' namespace is private namespace and do not make part of the interface. The backdoor class specified more explicitly which is the intent of this kind of classes.
Related Patterns
  • RAII (Resource Initialization Is Initialization): The component safe adapters usually use the RAII idiom in order to reach on destruction a stable state for the Component.
  • Extension object: The ComponentSafeAdapter can be seen as an Extension objects of the Component.

Sunday, April 11, 2010

Backdoor C++ Idiom - part II

After having see the motivation, let us now turn to generic problem and solution.

Context and Applicability
  • You are designing a class using a language such as C++, which provides public, protected and private access rights, constructor and destructor and in which friend classes can be declared.
  • The class offers some services that must be used with caution following a given protocol. If the guaranties are not ensured your system will crash.
  • This protocol can be ensured by third classes in multiple ways not know in advance by the class designer.
Problem

The class you are designing offers some services that must be used with caution following a given protocol, e.g. opened files must be closed, acquired mutex must be released, opened transaction must be suspended, committed or rolled back, suspended transaction must be resumed, or rolled back, resumed transactions must be suspended, committed or rolled back.
The program must be designed carefully to avoid these non-conformances. These errors aren't rare or exotic failures - they are virtually guaranteed to occur unless the interface is designed to avoid them.
Giving a public access would be dangerous, delegating to the client the responsibility to ensure a correct usage. Giving a private access to this services would force to declare the friend classes that are able to use this interface, while the class name and number which can correctly use this services are not known in advance.

Solution

Differentiate between two kinds of clients for your class:
  • Aware clients that are aware of the protocol constraints in order to construct safe interfaces adapter and
  • Unaware clients which use safe interfaces and which can be unaware of the protocol constraints.

Define a backdoor access to your class that acts as a bridge to your class. Allows friend access to the backdoor class.
Aware clients use the public interface and the back-door one with caution in order to respect the protocol constraints.
Unaware clients use the safe public interface and the Safe adapters.

Structure and Participants

The participants in the Backdoor idiom include the following:
Component: grants access to the BackdoorComponent
ComponentBackdoor: defines a restricted public interface to the private part of a component, which must be used with caution, and a protected one for the derived component backdoors.
ComponentSafeAdapter: Provides a safe mean for using the concept ensuring that the component protocol constraints are respected. ComponentSafeAdapter objects are constructed with a reference to a component object and use the ComponentBackdoor class aware of the protocol constraints. This class follows the RAII C++ idiom to ensure that on destruction the component instance is left on a stable state. A variant can be to left on an unstable state but be sure that the safety has been transferred before destruction to another object.
UnawareClient: uses the public interface of Component as well as the ComponentSafeAdapters.


Consequences
Benefits
  • The unsafe use has been limited to the aware component safe adapters.
  • The unaware client cannot use unsafe features and is guided by the component safe adapters.

Liabilities
  • The design is more complex, we have in addition to the component, a component back-door and several component safe adapters.
  • The backdoor interface must be designed carefully to open only the needed private services that help the component safe adapters design.
  • Modifications on the class interface may be synchronized on the backdoor interface.
  • The component designer can document and why not define helper “typedef” for the component safe adapters it knows the time the component is designed, but the other component safe adapters cannot be associated to the Component using the C++ language.
  • It is not possible with the C++ type system to know which clients are aware or not. Is the client using the backdoor interface which must be conscientious of its awareness in order to define a safe usage of the component ? One hint that could guide the client to know if it can use the backdoor interface would be to answer the question, “can this class be considered as an extension of the component interface, i.e. is a component safe adapter?”
Next part will concentrate on possible implementations in C++.

Wednesday, April 7, 2010

Backdoor C++ Idiom - part I

Intent

Provide a safe interface to a class that ensures its internal guaranties without closing too much the class interface.

Motivation

Designing a C++ concurrent library can be done in a simple way by defining a wrapper of the types, constants, and functions of an existing C thread library. For example the class mutex is used to ensure mutually exclusive access to data.
class mutex {
public:
// … 
  void lock();
  void unlock();
// … 
};
While the C++ wrapper interface can eliminate some of the C liabilities, it doesn't avoid the fact that client must master the protocol usage: the client must guarantee that the unlock function is called each time the lock function is called.
{
  mtx.lock();
  // … [a]
  // not called if an exception occurs in [a] 
  mtx.unlock();
}
A first step forward could consist in using the C++ scoped idiom (RAII) to define some scoped classes that will acquire the mutex on construction and release it on destruction.
class  mutex_strict_lock {
public :
  mutex_strict_lock(mutex& mtx) : mtx_(mtx) {
    mtx_.lock();
  }
  ~mutex_strict_lock(mutex&) {
    mtx_.unlock();
  }
private :
  mutex mtx_;
};
and use it in a scoped block:
{
  mutex_strict_lock guard(mutex);
  // … 
  // destructor called when exit from this block 
  // even on exception
}
While this reduces risk, it does not force the client to only use this safe mechanism in order to lock/unlock a mutex, since the lock and unlock functions remain public.
A second step could be to declare the lock/unlock functions private and to grant friend access to the mutex_strict_lock class.
class  mutex {
public:
  // ...
private:
  // … 
  void lock();
  void unlock();
  // … 
  friend class  mutex_strict_lock;
  // ...
};
Now the following code does not compiles
{
  mtx.lock(); // ERROR do not compile 
  // .. [a] 
  // not called if an exception occurs in [a]
  mtx.unlock();// ERROR do not compile
}
This ensures a safe use of the class but there is no other way to use a mutex, the interface to the mutex class is now close. Once the mutex is locked, it cannot be unlocked neither relocked as many times as the client considers pertinent. A close interface is less useful than an unsafe one.
The main problem with the mutex_strict_lock class is that even if it ensures the mutex guaranties, it adds another one; the mutex stays locked during the lifetime of the mutex_strict_lock instance. Moreover, the safe adapter must ensure the guaranties but not limit the initial set of functionalities. Sometimes this can be done with a single safe adapter class or with a set of safe adapters classes. So the designer of the class must define at least a minimal set of safe adapters that covers the whole set of functionalities. In the case of the mutex class, a mutex_scoped_lock can ensure the guaranties and satisfy all the functionalities.
Once we have a minimal set of safe adapters, the designer can find some other interesting usages of its class, which could in addition ensure other guaranties, and then grant friend access to all this classes.
class  mutex {
  // ... 
  friend class  mutex_scoped_lock;
  friend class  mutex_strict_lock;
  friend class  mutex_scoped_reverse_lock;
  //...
};
This could seems good, but the library designer can not pretend to know in advance all the safe usages of its library while each of the safe adapters needs to access the lock/unlock functions. There are other ways to ensure the guaranties, as a mutex_locking_ptr, mutex_scoped_locking_ptr, and surely many others. But now we cannot use these new safe classes without modifying the initial class.
What we are looking for is not to limit the safe usage of the initial class, but just to protect from unsafe usages. The idea is to define a two levels interface for a class, one being safe while the other is unsafe but only visible to safe aware clients. Evidently there is no means to check this safety awareness, but the fact the interface is split in two interfaces having different usages, helps the unaware client to identify the safe interface, and signals to the client that using the unsafe interface s/he must be aware of the unsafe features.

More coming soon, stay tunned.

Friday, April 2, 2010

Pimpl Static Variant

In a already old article "The Joy of Pimpls (or, More About the Compiler-Firewall Idiom)", Herbe Sutter states
There are four main alternative disciplines:
  • Put all private data (but not functions) into XImpl.
  • Put all private members into XImpl.
  • Put all private and protected members into XImpl.
  • Make XImpl entirely the class that X would have been, and write X as only the public interface made up entirely of simple forwarding functions (another handle/body variant).
My experience is that in some contexts we could add more private member functions than private member data. For example, when we apply the pattern "Methods for States - A Pattern for Realizing Object Lifecycles" from Kevlin Henney, we have a lot of internal function to represent transitions between states. A change in the implementation of the FSM means adding or removing transition. If these internal functions are declared at the class level, we need to modifying the header file.

I have explored a different variant
  • Put all private functions and static data (but not instance data) into XImpl. XImpl needs only to store the back pointer.
This variant avoid changing the header file in those cases. I will adapt the clock example from "Methods for States" to show how the variant works.
// clock.hpp
class clock {
public:
void change_mode() {
 (this->*(behavior->change_mode))();
}
void increment() {
  (this->*(behavior->increment))();
}
void tick() {
  (this->*(behavior->tick))();
}
private:
  typedef void (clock::*function)();
  struct mode {
    const function change_mode, increment, tick;
  };
  static const mode displaying_time
  static const mode setting_hours;
  static const mode setting_minutes;
  const mode *behavior;
  int hour, minute, second;

  template<const mode *next_mode>
  void change_to() {
behavior = next_mode;
  }
  void next_hour() {
hour = (hour + 1) % 24;
  }
  void next_minute() {
minute = (minute + 1) % 60;
  }
  void update_time() {
if(++second == 60) {
second = 0;
if(++minute == 60) {
minute = 0;
hour = (hour + 1) % 24;
    }
    }
  }
  void do_nothing() {}
};

// clock.cpp
const clock::mode clock::displaying_time = {
  &clock::change_to<&setting_hours>, 
&clock::do_nothing, 
&clock::update_time
};
const clock::mode clock::setting_hours = {
  &clock::change_to<&setting_minutes>, 
&clock::next_hour, 
&clock::do_nothing
};
const clock::mode clock::setting_minutes = {
  &clock::change_to<&displaying_time>, 
&clock::next_minute, 
&clock::do_nothing
};
Hiding internal functions and static data in the header file
Only the public interface, the private instance data and the grant friendship to impl appear on the header file.
// clock.hpp
class clock {
public:
  void change_mode();
  void increment();
  void tick();
private:
  struct impl; // forward declaration
  friend class impl;

  struct mode; // forward declaration
  const mode *behavior;
  int hour, minute, second;
};
Moving to the implementation file the private part
The types used only by the implementation go to the implementation file clock.cpp.
// clock.cpp
typedef void (clock::impl::*function)();
struct clock::mode {
  const function change_mode, increment, tick;
};
The class implementation follows always the same schema.
  • Define a variable referencing the class to implement, and
  • a constructor taking an instance of this class.
struct clock::impl {
clock& that;
impl(clock* thisClock) : that(*thisClock) {}
  ...
};
Next follows the private static data:
struct clock::impl {
  ...
  static const clock::mode displaying_time;
static const clock::mode setting_hours;
  static const clock::mode setting_minutes;
  ...
};
And the functions that were private
struct clock::impl {
  ...
  template<const clock::mode *next_mode>
  void change_to() {
that.behavior = next_mode;
  }
  void next_hour() {
that.hour = (that.hour + 1) % 24;
  }
  void next_minute() {
that.minute = (that.minute + 1) % 60;
  }
  void update_time() {
  if(++that.second == 60) {
that.second = 0;
     if(++that.minute == 60) {
that.minute = 0;
that.hour = (that.hour + 1) % 24;
     }
    }
  }
  void do_nothing() {}
};
The definition of the public functions need just to replace this-> by impl(this).
void clock::change_mode() {
 (impl(this).*(behavior->change_mode))();
}
void clock::increment() {
 (impl(this).*(behavior->increment))();
}
void clock::tick() {
 (impl(this).*(behavior->tick))();
}
Last, the static initialization is done.
const clock::mode clock::impl::displaying_time = {
  &clock::impl::change_to<&setting_hours>,
&clock::impl::do_nothing,
&clock::impl::update_time
};
const clock::mode clock::impl::setting_hours = {
  &clock::impl::change_to<&setting_minutes>,
&clock::impl::next_hour,
&clock::impl::do_nothing
};
const clock::mode clock::impl::setting_minutes = {
  &clock::impl::change_to<&displaying_time>,
&clock::impl::next_minute,
&clock::impl::do_nothing
};
While this approach doesn't encapsulates all the private members, it has some advantages:
  • The XImpl class has no inherent instance data, so no space overhead
  • The class doesn't needs to store any XImpl pointer as there is no data to maintain, so no need to allocate/deallocate it.
  • Reduce the performance overhead of the Pimpl idiom.
The drawbacks are:
  • Need to include the headers declaring the private instance data types.
  • There is yet a minimal performance overhead on the construction of the temporary XImpl class and the dereference of the back pointer.