Revert "update IPC_CONCEPT_"

This reverts commit 1e5547e6dfd0605fa62be67899c6c893aa61f9fc.
This commit is contained in:
mutouyun 2021-06-06 19:40:54 +08:00
parent 85342dcaa6
commit 12944502a1
6 changed files with 46 additions and 62 deletions

View File

@ -44,8 +44,7 @@ constexpr std::size_t aligned(std::size_t size, size_t alignment) noexcept {
return ( (size - 1) & ~(alignment - 1) ) + alignment;
}
template <typename T>
IPC_CONCEPT_(has_take, require<T>([](auto && t)->decltype(t.take(std::move(t))) {}));
IPC_CONCEPT_(has_take, take(std::move(std::declval<Type>())));
class scope_alloc_base {
protected:
@ -117,13 +116,13 @@ public:
}
template <typename A = AllocP>
auto take(scope_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
auto take(scope_alloc && rhs) -> ipc::require<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) -> std::enable_if_t<!detail::has_take<A>::value> {
auto take(scope_alloc && rhs) -> ipc::require<!detail::has_take<A>::value> {
base_t::take(std::move(rhs));
}
@ -256,7 +255,7 @@ public:
}
template <typename A = AllocP>
auto take(fixed_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
auto take(fixed_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
base_t::take(std::move(rhs));
alloc_.take(std::move(rhs.alloc_));
}
@ -395,7 +394,7 @@ public:
}
template <typename A = AllocP>
auto take(variable_alloc && rhs) -> std::enable_if_t<detail::has_take<A>::value> {
auto take(variable_alloc && rhs) -> ipc::require<detail::has_take<A>::value> {
base_t::take(std::move(rhs));
alloc_.take(std::move(rhs.alloc_));
}

View File

@ -27,8 +27,7 @@ namespace mem {
namespace detail {
template <typename T>
IPC_CONCEPT_(is_comparable, require<const T>([](auto && t)->decltype(t < t) {}));
IPC_CONCEPT_(is_comparable, operator<(std::declval<Type>()));
} // namespace detail
@ -72,10 +71,8 @@ public:
template <typename AllocP>
class default_recycler : public limited_recycler<AllocP> {
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()) {}));
IPC_CONCEPT_(has_remain, remain());
IPC_CONCEPT_(has_empty , empty());
template <typename A>
void try_fill(A & alc) {
@ -89,28 +86,28 @@ public:
template <typename A = AllocP>
auto try_replenish(alloc_policy & alc, std::size_t size)
-> std::enable_if_t<detail::has_take<A>::value && has_remain<A>::value> {
-> ipc::require<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*/)
-> std::enable_if_t<detail::has_take<A>::value && !has_remain<A>::value && has_empty<A>::value> {
-> ipc::require<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*/)
-> std::enable_if_t<!detail::has_take<A>::value && has_empty<A>::value> {
-> ipc::require<!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
-> std::enable_if_t<(!detail::has_take<A>::value || !has_remain<A>::value) && !has_empty<A>::value> {
-> ipc::require<(!detail::has_take<A>::value || !has_remain<A>::value) && !has_empty<A>::value> {
// Do Nothing.
}
};

View File

@ -7,6 +7,7 @@
* @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

View File

@ -15,14 +15,19 @@
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>
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> {})
);
struct is_same_char<T, U, std::true_type> : std::is_same<T, typename U::value_type> {};
template <typename T, typename S, typename R = S>
using IsSameChar = std::enable_if_t<has_same_char<T, S>::value, R>;
using IsSameChar = ipc::require<is_same_char<T, S>::value, R>;
////////////////////////////////////////////////////////////////
/// to_tchar implementation

View File

@ -1,42 +1,29 @@
#pragma once
#include <type_traits> // std::declval
#include <type_traits> // std::enable_if
namespace ipc {
/**
* @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 {
// concept helpers
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
template <bool Cond, typename R = void>
using require = typename std::enable_if<Cond, R>::type;
#ifdef IPC_CONCEPT_
# error "IPC_CONCEPT_ has been defined."
#endif
#define IPC_CONCEPT_($$name, $$what) \
class $$name { \
#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: \
constexpr static bool value = $$what; \
using type = decltype(check<T>(nullptr)); \
constexpr static auto value = type::value; \
}
} // namespace ipc

View File

@ -8,19 +8,14 @@
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 {};