Boost logo

Boost :

Subject: Re: [boost] pimpl library proposal
From: Krzysztof Czainski (1czajnik_at_[hidden])
Date: 2010-12-05 13:25:39


2010/12/4 Michael Bailey <jinxidoru_at_[hidden]>

>
> ---- boost/pimpl.hpp ----
>
> #include <boost/typeof/typeof.hpp>
> #include <boost/type_traits/function_traits.hpp>
> #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
> #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
> #include <boost/preprocessor/repetition/enum_params.hpp>
> #include <boost/preprocessor/repetition/enum_shifted.hpp>
> #include <boost/preprocessor/arithmetic/inc.hpp>
>
> namespace boost {
>
> template <typename T>
> class pimpl {
> public:
>
> typedef T* ptr_type;
>
> pimpl( ptr_type p = new T() )
> : m_impl( p )
> {}
>
> ~pimpl() {
> delete m_impl;
> }
>
>
> protected:
>
> T& impl() { return *m_impl; }
> const T& impl() const { return *m_impl; }
>
>
> private:
> ptr_type m_impl;
> };
>
>
> template <typename T>
> struct method_traits;
>
> #ifndef BOOST_METHOD_TRAITS_LIMIT
> # define BOOST_METHOD_TRAITS_LIMIT 10
> #endif
>
> #define BOOST_METHOD_TRAITS(z,n,data) \
> template <typename C, typename R \
> BOOST_PP_ENUM_TRAILING_PARAMS_Z(z,n,class T) > \
> struct method_traits< R(C::*)( BOOST_PP_ENUM_PARAMS_Z(z,n,T) ) data > \
> : public function_traits< R( BOOST_PP_ENUM_PARAMS_Z(z,n,T) ) > { \
> typedef data C class_type; \
> };
>
> BOOST_PP_REPEAT(BOOST_METHOD_TRAITS_LIMIT,BOOST_METHOD_TRAITS,)
> BOOST_PP_REPEAT(BOOST_METHOD_TRAITS_LIMIT,BOOST_METHOD_TRAITS,const)
> BOOST_PP_REPEAT(BOOST_METHOD_TRAITS_LIMIT,BOOST_METHOD_TRAITS,volatile)
> BOOST_PP_REPEAT(BOOST_METHOD_TRAITS_LIMIT,BOOST_METHOD_TRAITS,const
> volatile)
>
>
> }
>
> #define BOOST_PIMPL_CTOR( cls ) \
> cls::cls() {}
>
> #define BOOST_PIMPL_DEFINE_METHOD_M( z, n, data ) \
> BOOST_JOIN(BOOST_JOIN(data::arg,n),_type) BOOST_JOIN(a,n)
>
> #define BOOST_PIMPL_METHOD( args, cls, meth, ... ) \
> ::boost::method_traits< BOOST_TYPEOF(&cls::meth) >::result_type \
> cls::meth( \
> BOOST_PP_ENUM_SHIFTED( BOOST_PP_INC(args), \
> BOOST_PIMPL_DEFINE_METHOD_M, \
> ::boost::method_traits<typeof(&cls::meth)> \
> ) \
> ) __VA_ARGS__ { \
> return impl().meth( \
> BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(args),a) \
> ); \
> }
>

Hello,

I would like to see some pimpl idiom library in boost. I have tackled the
problem of simplifying pimpl implementation a while ego. I begun by
designing a base class (similar to Your approach, Michael). In the end,
however, I came up with a value_ptr class, which is a bit more general, then
just for pimpl idiom. I thought to propose it to boost, but I haven't (yet).
By now I have used It many times, and I am happy with it.

/**
 * Smart pointer adaptor, that preserves constness of @c element_type, and
upon construction
 * allocates the object using @c new, and forwards constructor arguments.
 *
 * It is perfect for the PIMPL idiom.
 *
 * @tparam SmartPtr Underlying smart pointer, owning the object.
 */
template < class SmartPtr, class Element = typename pointee<SmartPtr>::type,
        class ValuePtrAllocator = value_ptr_heap_allocator<SmartPtr> >
class value_ptr;

MyClass.h:

class MyClass
{
public:
  MyClass(); // needed, but trivial
  ~MyClass(); // sometimes needed, but trivial
  // methods...
private:
  struct Impl;
  value_ptr< scoped_ptr<Impl> > impl_;
};

MyClass.cpp:

struct MyClass::Impl
{/*...*/};

MyClass::MyClass()
{} // value_ptr automatically allocates an Impl instance

MyClass::~MyClass()
{} // value_ptr automatically deallocates Impl

// methods...

So, we gain:
- easy allocation (without explicit call to new, which avoids possible
problems with exception safety if we need to call some throwing operations
in the ctor),
- value_ptr has a set of templated ctors, which forward args to Impl's ctor,
- allocation is customizable by value_ptr's third template parameter,
- automatic deallocation, which is done by the underlying SmartPtr
(scoped_ptr, shared_ptr, or some other ptr like clone_ptr can be used),
- const-correct versions of operator* and -> with respect to the fact, that
MyClass logically owns it's Impl.

Right now I can't spend more time on trying to understand how the method
macros proposed by Michael work (I'm not familiar with advanced macros), but
I like the Idea, and I am looking forward to adding those to value_ptr in
the future ;-)

The source code for value_ptr together with a few other related tools can be
found here:
https://libcz.svn.sourceforge.net/svnroot/libcz/trunk/boost

Regards,
Kris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk