
2010/12/4 Michael Bailey <jinxidoru@gmail.com>
---- 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