1. 4FipS.com
  2. Photos
  3. Videos
  4. Code
  5. Forums
  6. pfQuizzz
  7. About

4FipS.com Forums

Forums dedicated to the projects hosted at 4FipS.com

Skip to content

PIMPL using std::unique_ptr with incomplete types (C++)

> About coding, hacking, photography, and such...

PIMPL using std::unique_ptr with incomplete types (C++)

Postby FipS on Wed Apr 11, 2012 8:15 pm

I've been using the PIMPL idiom with great success in various scenarios, ranging from minimizing dependencies and speeding up compilation to hiding platform specific types on the implementation side. For example, all my OpenGL resources like Vertex Buffers, Textures, etc. lives peacefully behind PIMPL. The great thing about implementing PIMPL using std::unique_ptr is the fact that it can handle incomplete types. However, there's something one should be aware of. According to the rules described here, the type that uses PIMPL needs to define a destructor (with its implementation in CPP), otherwise it doesn't compile.

Below, you can find an example of a std::unique_ptr-PIMPled type with move semantics, which shows what I tend to use most of the time:

foo.h
Code: Select all
/*
(c) 2012 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=715
*/

#ifndef FS_HEADER__foo_h__GUARD
#define FS_HEADER__foo_h__GUARD

#include <memory>

class Foo // non-copyable, movable, PIMPLed type
{
 public:

    Foo();
    ~Foo(); // DTOR required when PIMPL uses 'std::unique_ptr'!

    Foo(Foo&& rhs); // move constructor
    Foo& operator=(Foo&& rhs); // move assignment

    void bar();

 private:

    Foo(const Foo&); // non-copyable ('= delete' in C++11)
    Foo& operator=(const Foo&); // non-copyable ('= delete' in C++11)

    // a complete type is not required in the case of 'std::unique_ptr',
    // however, 'Foo' needs to define a DTOR with its implementation in
    // CPP, otherwise it doesn't compile (note that this is not required
    // in the case of 'std::shared_ptr')

    class Impl;
    std::unique_ptr<Impl> _impl;
};

#endif // FS_HEADER__foo_h__GUARD


foo.cpp
Code: Select all
/*
(c) 2012 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=715
*/

#include "foo.h"
#include <iostream>

class Foo::Impl
{
 public:

    Impl() {}
    void bar() { std::cout << "Foo::Impl::bar();\n"; }

 private:

    Impl(const Impl&); // non-copyable ('= delete' in C++11)
    Impl& operator=(const Impl&); // non-copyable ('= delete' in C++11)
};

// forwards:

Foo::Foo() : _impl(new Impl) {}
Foo::~Foo() {} // required by 'std::unique_ptr'!

Foo::Foo(Foo&& rhs) : _impl(std::move(rhs._impl)) {}
Foo& Foo::operator=(Foo&& rhs) { _impl = std::move(rhs._impl); return *this; }

void Foo::bar() { _impl->bar(); }


main.cpp
Code: Select all
/*
(c) 2012 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=715
*/

#include "foo.h"

int main()
{
    Foo foo;
    foo.bar();

    Foo bar = std::move(foo); // moves, steals '_impl' from 'foo'
    bar.bar();

    //Foo baz = bar; // DOESN'T COMPILE!, 'Foo' is non-copyable
}

// output:
// Foo::Impl::bar();
// Foo::Impl::bar();
User avatar
FipS
Site Admin
 
Posts: 146
Joined: Wed Nov 12, 2008 9:49 pm
Location: Prague

PIMPL using std::unique_ptr with incomplete types (C++)

Sponsor

Sponsor
 

Return to 4FipS.com General Discussion & Blog

Who is online

Users browsing this forum: Baidu [Spider] and 1 guest

cron