Last active
August 29, 2015 14:15
-
-
Save Hebali/a363d84c1ed4e0c30027 to your computer and use it in GitHub Desktop.
PIMPL Idiom in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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