Skip to content

Instantly share code, notes, and snippets.

@Hebali
Last active August 29, 2015 14:15
Show Gist options
  • Save Hebali/a363d84c1ed4e0c30027 to your computer and use it in GitHub Desktop.
Save Hebali/a363d84c1ed4e0c30027 to your computer and use it in GitHub Desktop.
PIMPL Idiom in C++
// PIMPL Idiom
// Example by Patrick Hebron
#include <memory>
#include <string>
#include <iostream>
/** @brief templated pimpl wrapper */
template <typename Impl> class pimpl_t {
public:
typedef std::shared_ptr<pimpl_t> ref; //!< shared_ptr type for pimpl wrapper
private:
std::unique_ptr<Impl> m_impl; //!< the implementation object
/** @brief explicit argument-forwarding constructor */
template <typename ... Args> explicit pimpl_t(Args&& ... args)
: m_impl( std::unique_ptr<Impl>( new Impl( std::forward<Args>( args )... ) ) ) { /* no-op */ }
public:
/** @brief destructor */
~pimpl_t() { /* no-op */ }
/** @brief static creational method */
template <typename ... Args> static pimpl_t::ref create(Args&& ... args)
{
return pimpl_t::ref( new pimpl_t( std::forward<Args>( args )... ) );
}
/** @brief argument-forwarding construction setter */
template <typename ... Args> void set_ptr(Args&& ... args)
{
m_impl = std::unique_ptr<Impl>( new Impl( std::forward<Args>( args )... ) );
}
/** @brief returns const pointer to implementation */
const Impl* get_ptr() const
{
return m_impl.get();
}
/** @brief returns pointer to implementation */
Impl* get_ptr()
{
return m_impl.get();
}
/** @brief returns const reference to implementation */
const Impl& get_ref() const
{
return *( m_impl.get() );
}
/** @brief returns reference to implementation */
Impl& get_ref()
{
return *( m_impl.get() );
}
};
struct TestType
{
std::string m_name;
int m_id;
TestType(const std::string& i_name, const int& i_id)
: m_name( i_name ), m_id( i_id ) { /* no-op */ }
};
static inline void print_item(const std::string& label, const pimpl_t<TestType>::ref& item)
{
std::cout
<< label << "( " << &item << ", " << item->get_ptr() << " )"
<< " = { " << item->get_ptr()->m_name << ", " << item->get_ptr()->m_id << " }" << std::endl;
}
int main(int argc, const char * argv[])
{
pimpl_t<TestType>::ref a;
pimpl_t<TestType>::ref b;
a = pimpl_t<TestType>::create( "foo", 1234 );
b = a;
print_item( "a", a );
print_item( "b", b );
std::cout << std::endl;
a->set_ptr( "bar", 2345 );
print_item( "a", a );
print_item( "b", b );
std::cout << std::endl;
b->set_ptr( "baz", 3456 );
print_item( "a", a );
print_item( "b", b );
std::cout << std::endl;
a->get_ptr()->m_name = "qux";
print_item( "a", a );
print_item( "b", b );
std::cout << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment