mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
update IPC_CONCEPT_
This commit is contained in:
parent
57e5298006
commit
8cd2a40bfd
@ -44,7 +44,8 @@ constexpr std::size_t aligned(std::size_t size, size_t alignment) noexcept {
|
||||
return ( (size - 1) & ~(alignment - 1) ) + alignment;
|
||||
}
|
||||
|
||||
IPC_CONCEPT_(has_take, take(std::move(std::declval<Type>())));
|
||||
template <typename T>
|
||||
IPC_CONCEPT_(has_take, require<T>([](auto && t)->decltype(t.take(std::move(t))) {}));
|
||||
|
||||
class scope_alloc_base {
|
||||
protected:
|
||||
@ -116,13 +117,13 @@ public:
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto take(scope_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
|
||||
auto take(scope_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
|
||||
base_t::take(std::move(rhs));
|
||||
alloc_.take(std::move(rhs.alloc_));
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto take(scope_alloc && rhs) -> ipc::require<!detail::has_take<A>::value> {
|
||||
auto take(scope_alloc && rhs) -> std::enable_if_t<!detail::has_take<A>::value> {
|
||||
base_t::take(std::move(rhs));
|
||||
}
|
||||
|
||||
@ -255,7 +256,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto take(fixed_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
|
||||
auto take(fixed_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
|
||||
base_t::take(std::move(rhs));
|
||||
alloc_.take(std::move(rhs.alloc_));
|
||||
}
|
||||
@ -394,7 +395,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto take(variable_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
|
||||
auto take(variable_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
|
||||
base_t::take(std::move(rhs));
|
||||
alloc_.take(std::move(rhs.alloc_));
|
||||
}
|
||||
|
||||
@ -27,7 +27,8 @@ namespace mem {
|
||||
|
||||
namespace detail {
|
||||
|
||||
IPC_CONCEPT_(is_comparable, operator<(std::declval<Type>()));
|
||||
template <typename T>
|
||||
IPC_CONCEPT_(is_comparable, require<const T>([](auto && t)->decltype(t < t) {}));
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@ -71,8 +72,10 @@ public:
|
||||
template <typename AllocP>
|
||||
class default_recycler : public limited_recycler<AllocP> {
|
||||
|
||||
IPC_CONCEPT_(has_remain, remain());
|
||||
IPC_CONCEPT_(has_empty , empty());
|
||||
template <typename T>
|
||||
IPC_CONCEPT_(has_remain, require<const T>([](auto && t)->decltype(t.remain()) {}));
|
||||
template <typename T>
|
||||
IPC_CONCEPT_(has_empty, require<const T>([](auto && t)->decltype(t.empty()) {}));
|
||||
|
||||
template <typename A>
|
||||
void try_fill(A & alc) {
|
||||
@ -86,28 +89,28 @@ public:
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto try_replenish(alloc_policy & alc, std::size_t size)
|
||||
-> ipc::require<detail::has_take<A>::value && has_remain<A>::value> {
|
||||
-> std::enable_if_t<detail::has_take<A>::value && has_remain<A>::value> {
|
||||
if (alc.remain() >= size) return;
|
||||
this->try_fill(alc);
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
|
||||
-> ipc::require<detail::has_take<A>::value && !has_remain<A>::value && has_empty<A>::value> {
|
||||
-> std::enable_if_t<detail::has_take<A>::value && !has_remain<A>::value && has_empty<A>::value> {
|
||||
if (!alc.empty()) return;
|
||||
this->try_fill(alc);
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
auto try_replenish(alloc_policy & alc, std::size_t /*size*/)
|
||||
-> ipc::require<!detail::has_take<A>::value && has_empty<A>::value> {
|
||||
-> std::enable_if_t<!detail::has_take<A>::value && has_empty<A>::value> {
|
||||
if (!alc.empty()) return;
|
||||
this->try_recover(alc);
|
||||
}
|
||||
|
||||
template <typename A = AllocP>
|
||||
IPC_CONSTEXPR_ auto try_replenish(alloc_policy & /*alc*/, std::size_t /*size*/) noexcept
|
||||
-> ipc::require<(!detail::has_take<A>::value || !has_remain<A>::value) && !has_empty<A>::value> {
|
||||
-> std::enable_if_t<(!detail::has_take<A>::value || !has_remain<A>::value) && !has_empty<A>::value> {
|
||||
// Do Nothing.
|
||||
}
|
||||
};
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
* @remarks
|
||||
* Windows doesn't support a per-thread destructor with its TLS primitives.
|
||||
* So, here will build it manually by inserting a function to be called on each thread's exit.
|
||||
*
|
||||
* @see
|
||||
* - https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
|
||||
* - https://src.chromium.org/viewvc/chrome/trunk/src/base/threading/thread_local_storage_win.cc
|
||||
|
||||
@ -15,19 +15,14 @@
|
||||
namespace ipc {
|
||||
namespace detail {
|
||||
|
||||
struct has_value_type_ {
|
||||
template <typename T> static std::true_type check(typename T::value_type *);
|
||||
template <typename T> static std::false_type check(...);
|
||||
};
|
||||
|
||||
template <typename T, typename U, typename = decltype(has_value_type_::check<U>(nullptr))>
|
||||
struct is_same_char : std::is_same<T, U> {};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same_char<T, U, std::true_type> : std::is_same<T, typename U::value_type> {};
|
||||
IPC_CONCEPT_(has_same_char,
|
||||
require([]()->std::enable_if_t<std::is_same<T, typename U::value_type>::value> {}) ||
|
||||
require([]()->std::enable_if_t<std::is_same<T, U>::value> {})
|
||||
);
|
||||
|
||||
template <typename T, typename S, typename R = S>
|
||||
using IsSameChar = ipc::require<is_same_char<T, S>::value, R>;
|
||||
using IsSameChar = std::enable_if_t<has_same_char<T, S>::value, R>;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/// to_tchar implementation
|
||||
|
||||
@ -1,29 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <type_traits> // std::declval
|
||||
|
||||
namespace ipc {
|
||||
|
||||
// concept helpers
|
||||
/**
|
||||
* @remarks
|
||||
* <<Concepts emulation>> Concepts TS Improve on C++17
|
||||
* @see
|
||||
* - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0726r0.html
|
||||
* - https://www.youtube.com/watch?v=TorW5ekkL_w
|
||||
*/
|
||||
namespace detail {
|
||||
|
||||
template <bool Cond, typename R = void>
|
||||
using require = typename std::enable_if<Cond, R>::type;
|
||||
template <typename F, typename... Args,
|
||||
typename = decltype(std::declval<F&&>()(std::declval<Args&&>()...))>
|
||||
constexpr bool require_impl(int) { return true; }
|
||||
|
||||
template <typename F, typename... Args>
|
||||
constexpr bool require_impl(...) { return false; }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Args, typename F>
|
||||
constexpr bool require(F&&) {
|
||||
return detail::require_impl<F&&, Args&&...>(int{});
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
/// concept helpers
|
||||
|
||||
#ifdef IPC_CONCEPT_
|
||||
# error "IPC_CONCEPT_ has been defined."
|
||||
#endif
|
||||
|
||||
#define IPC_CONCEPT_(NAME, WHAT) \
|
||||
template <typename T> \
|
||||
class NAME { \
|
||||
private: \
|
||||
template <typename Type> \
|
||||
static std::true_type check(decltype(std::declval<Type>().WHAT)*); \
|
||||
template <typename Type> \
|
||||
static std::false_type check(...); \
|
||||
public: \
|
||||
using type = decltype(check<T>(nullptr)); \
|
||||
constexpr static auto value = type::value; \
|
||||
#define IPC_CONCEPT_($$name, $$what) \
|
||||
class $$name { \
|
||||
public: \
|
||||
constexpr static bool value = $$what; \
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
@ -8,14 +8,19 @@
|
||||
|
||||
namespace ipc {
|
||||
|
||||
template <typename T>
|
||||
IPC_CONCEPT_(is_impl_comfortable,
|
||||
require<T>([](auto && t)->std::enable_if_t<(sizeof(t) <= sizeof(T*))> {})
|
||||
);
|
||||
|
||||
template <typename T, typename R = T*>
|
||||
using IsImplComfortable = std::enable_if_t<is_impl_comfortable<T>::value, R>;
|
||||
|
||||
template <typename T, typename R = T*>
|
||||
using IsImplUncomfortable = std::enable_if_t<!is_impl_comfortable<T>::value, R>;
|
||||
|
||||
// pimpl small object optimization helpers
|
||||
|
||||
template <typename T, typename R = T*>
|
||||
using IsImplComfortable = ipc::require<(sizeof(T) <= sizeof(T*)), R>;
|
||||
|
||||
template <typename T, typename R = T*>
|
||||
using IsImplUncomfortable = ipc::require<(sizeof(T) > sizeof(T*)), R>;
|
||||
|
||||
template <typename T, typename... P>
|
||||
constexpr auto make_impl(P&&... params) -> IsImplComfortable<T> {
|
||||
T* buf {};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user