mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
74 lines
1.7 KiB
C++
74 lines
1.7 KiB
C++
/**
|
|
* @file libimp/pimpl.h
|
|
* @author mutouyun (orz@orzz.org)
|
|
* @brief Pointer To Implementation (pImpl) idiom
|
|
* @date 2022-02-27
|
|
*/
|
|
#pragma once
|
|
|
|
#include <utility>
|
|
#include <type_traits>
|
|
#include <cstdint>
|
|
|
|
#include "libimp/construct.h"
|
|
#include "libimp/def.h"
|
|
|
|
LIBIMP_NAMESPACE_BEG_
|
|
namespace pimpl {
|
|
|
|
template <typename T, typename R = T *>
|
|
struct is_comfortable {
|
|
enum : bool {
|
|
value = (sizeof(T) <= sizeof(R)) && (alignof(T) <= alignof(R))
|
|
};
|
|
};
|
|
|
|
template <typename T, typename... A>
|
|
auto make(A &&... args) -> std::enable_if_t<is_comfortable<T>::value, T *> {
|
|
T *buf {};
|
|
// construct an object using memory of a pointer
|
|
construct<T>(&buf, std::forward<A>(args)...);
|
|
return buf;
|
|
}
|
|
|
|
template <typename T>
|
|
auto get(T * const (& p)) noexcept -> std::enable_if_t<is_comfortable<T>::value, T *> {
|
|
return reinterpret_cast<T*>(&const_cast<char &>(reinterpret_cast<char const &>(p)));
|
|
}
|
|
|
|
template <typename T>
|
|
auto clear(T *p) noexcept -> std::enable_if_t<is_comfortable<T>::value> {
|
|
if (p != nullptr) destroy(get(p));
|
|
}
|
|
|
|
template <typename T, typename... A>
|
|
auto make(A &&... args) -> std::enable_if_t<!is_comfortable<T>::value, T *> {
|
|
return new T{std::forward<A>(args)...};
|
|
}
|
|
|
|
template <typename T>
|
|
auto get(T * const (& p)) noexcept -> std::enable_if_t<!is_comfortable<T>::value, T *> {
|
|
return p;
|
|
}
|
|
|
|
template <typename T>
|
|
auto clear(T *p) noexcept -> std::enable_if_t<!is_comfortable<T>::value> {
|
|
if (p != nullptr) delete p;
|
|
}
|
|
|
|
template <typename T>
|
|
class Obj {
|
|
public:
|
|
template <typename... A>
|
|
static T *make(A &&... args) {
|
|
return pimpl::make<T>(std::forward<A>(args)...);
|
|
}
|
|
|
|
void clear() noexcept {
|
|
pimpl::clear(static_cast<T *>(const_cast<Obj *>(this)));
|
|
}
|
|
};
|
|
|
|
} // namespace pimpl
|
|
LIBIMP_NAMESPACE_END_
|