Skip to content

Instantly share code, notes, and snippets.

@dimitarcl
Created September 23, 2012 14:08
Show Gist options
  • Save dimitarcl/3771331 to your computer and use it in GitHub Desktop.
Save dimitarcl/3771331 to your computer and use it in GitHub Desktop.
A twist on PImpl
?GetPort@HTTPServer@@QBEGXZ PROC ; HTTPServer::GetPort, COMDAT
; _this$ = ecx
mov ax, WORD PTR [ecx]
ret 0
#include "HTTPServer.h"
#include "HTTPServerImpl.h"
HTTPServer::HTTPServer(unsigned short port)
: m_Impl(port)
{
}
HTTPServer::~HTTPServer()
{
}
unsigned short HTTPServer::GetPort() const
{
return m_Impl->GetPort();
}
#include "Impl.h"
class HTTPServerImpl;
class HTTPServer
{
public:
HTTPServer(unsigned short port);
~HTTPServer();
unsigned short GetPort() const;
private:
Impl<HTTPServerImpl, 8> m_Impl;
};
?GetPort@HTTPServer@@QBEGXZ PROC ; HTTPServer::GetPort, COMDAT
; _this$ = ecx
mov eax, DWORD PTR [ecx]
mov ax, WORD PTR [eax]
ret 0
#include "HTTPServerClassic.h"
#include "HTTPServerImpl.h"
HTTPServer::HTTPServer(unsigned short port)
: m_Impl(new HTTPServerImpl(port))
{
}
HTTPServer::~HTTPServer()
{
}
unsigned short HTTPServer::GetPort() const
{
return m_Impl->GetPort();
}
#pragma once
#include <memory>
class HTTPServerImpl;
class HTTPServer
{
public:
HTTPServer(unsigned short port);
~HTTPServer();
unsigned short GetPort() const;
private:
std::unique_ptr<HTTPServerImpl> m_Impl;
};
#pragma once
class HTTPServerImpl
{
public:
HTTPServerImpl(unsigned short port)
: m_Port(port)
{
}
unsigned short GetPort() const
{
return m_Port;
}
private:
unsigned short m_Port;
};
#pragma once
#include <new>
#include <utility>
// Visual Studio 2010 does not support std::max_align_t,
// so use an arbitrary default and leave it for clients to specify better value
template <typename T, size_t size, size_t alignment = sizeof(unsigned long long)>
class Impl
{
public:
Impl()
{
new (Get()) T;
}
template <typename Arg1>
Impl(Arg1&& arg1)
{
new (Get()) T(std::forward<Arg1>(arg1));
}
template <typename Arg1, typename Arg2>
Impl(Arg1&& arg1, Arg2&& arg2)
{
new (Get()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2));
}
Impl& operator=(const Impl& rhs)
{
*Get() = *rhs.Get();
}
Impl& operator=(Impl&& rhs)
{
*Get() = std::move(*rhs.Get());
}
~Impl()
{
static_assert(sizeof(T) <= size,
"Implementation instance does not fit in the buffer");
static_assert(alignment % std::alignment_of<T>::value == 0,
"Implementation instance has incompatible alignment requirements");
Get()->~T();
}
T* Get()
{
return reinterpret_cast<T*>(&m_Buffer);
}
const T* Get() const
{
return reinterpret_cast<const T*>(&m_Buffer);
}
T* operator->()
{
return Get();
}
const T* operator->() const
{
return Get();
}
private:
typedef typename std::aligned_storage<size, alignment>::type AlignedStorage;
AlignedStorage m_Buffer;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment