forked from OctaForge/libostd
use standard function
This commit is contained in:
parent
faa8c95486
commit
780f7e5b21
|
@ -19,7 +19,7 @@ namespace detail {
|
|||
SignalBase(SignalBase const &ev):
|
||||
p_class(ev.p_class), p_nfuncs(ev.p_nfuncs)
|
||||
{
|
||||
using Func = Function<void(C &, A...)>;
|
||||
using Func = std::function<void(C &, A...)>;
|
||||
byte *bufp = new byte[sizeof(Func) * p_nfuncs];
|
||||
Func *nbuf = reinterpret_cast<Func *>(bufp);
|
||||
for (Size i = 0; i < p_nfuncs; ++i)
|
||||
|
@ -34,7 +34,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
SignalBase &operator=(SignalBase const &ev) {
|
||||
using Func = Function<void(C &, A...)>;
|
||||
using Func = std::function<void(C &, A...)>;
|
||||
p_class = ev.p_class;
|
||||
p_nfuncs = ev.p_nfuncs;
|
||||
byte *bufp = new byte[sizeof(Func) * p_nfuncs];
|
||||
|
@ -54,8 +54,9 @@ namespace detail {
|
|||
~SignalBase() { clear(); }
|
||||
|
||||
void clear() {
|
||||
using func = std::function<void(C &, A...)>;
|
||||
for (Size i = 0; i < p_nfuncs; ++i) {
|
||||
p_funcs[i].~Function<void(C &, A...)>();
|
||||
p_funcs[i].~func();
|
||||
}
|
||||
delete[] reinterpret_cast<byte *>(p_funcs);
|
||||
p_funcs = nullptr;
|
||||
|
@ -64,7 +65,7 @@ namespace detail {
|
|||
|
||||
template<typename F>
|
||||
Size connect(F &&func) {
|
||||
using Func = Function<void(C &, A...)>;
|
||||
using Func = std::function<void(C &, A...)>;
|
||||
for (Size i = 0; i < p_nfuncs; ++i) {
|
||||
if (!p_funcs[i]) {
|
||||
p_funcs[i] = std::forward<F>(func);
|
||||
|
@ -121,7 +122,7 @@ namespace detail {
|
|||
|
||||
private:
|
||||
C *p_class;
|
||||
Function<void(C &, A...)> *p_funcs;
|
||||
std::function<void(C &, A...)> *p_funcs;
|
||||
Size p_nfuncs;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* Function objects for OctaSTD.
|
||||
*
|
||||
* This file is part of OctaSTD. See COPYING.md for futher information.
|
||||
* Portions of this file are originally adapted from the libc++ project.
|
||||
*/
|
||||
|
||||
#ifndef OSTD_FUNCTIONAL_HH
|
||||
|
@ -440,550 +439,6 @@ typename ToHash<T>::Result to_hash(T const &v) {
|
|||
return ToHash<T>()(v);
|
||||
}
|
||||
|
||||
/* mem_fn */
|
||||
|
||||
namespace detail {
|
||||
template<typename, typename>
|
||||
struct MemTypes;
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct MemTypes<T, R(A...)> {
|
||||
using Result = R;
|
||||
using Argument = T;
|
||||
};
|
||||
template<typename T, typename R, typename A>
|
||||
struct MemTypes<T, R(A)> {
|
||||
using Result = R;
|
||||
using FirstArgument = T;
|
||||
using SecondArgument = A;
|
||||
};
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct MemTypes<T, R(A...) const> {
|
||||
using Result = R;
|
||||
using Argument = T const;
|
||||
};
|
||||
template<typename T, typename R, typename A>
|
||||
struct MemTypes<T, R(A) const> {
|
||||
using Result = R;
|
||||
using FirstArgument = T const;
|
||||
using SecondArgument = A;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
class MemFn: MemTypes<T, R> {
|
||||
R T::*p_ptr;
|
||||
public:
|
||||
MemFn(R T::*ptr): p_ptr(ptr) {}
|
||||
template<typename... A>
|
||||
auto operator()(T &obj, A &&...args) ->
|
||||
decltype(((obj).*(p_ptr))(std::forward<A>(args)...))
|
||||
{
|
||||
return ((obj).*(p_ptr))(std::forward<A>(args)...);
|
||||
}
|
||||
template<typename... A>
|
||||
auto operator()(T const &obj, A &&...args) ->
|
||||
decltype(((obj).*(p_ptr))(std::forward<A>(args)...))
|
||||
const {
|
||||
return ((obj).*(p_ptr))(std::forward<A>(args)...);
|
||||
}
|
||||
template<typename... A>
|
||||
auto operator()(T *obj, A &&...args) ->
|
||||
decltype(((obj)->*(p_ptr))(std::forward<A>(args)...))
|
||||
{
|
||||
return ((obj)->*(p_ptr))(std::forward<A>(args)...);
|
||||
}
|
||||
template<typename... A>
|
||||
auto operator()(T const *obj, A &&...args) ->
|
||||
decltype(((obj)->*(p_ptr))(std::forward<A>(args)...))
|
||||
const {
|
||||
return ((obj)->*(p_ptr))(std::forward<A>(args)...);
|
||||
}
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename R, typename T>
|
||||
detail::MemFn<R, T> mem_fn(R T:: *ptr) {
|
||||
return detail::MemFn<R, T>(ptr);
|
||||
}
|
||||
|
||||
/* function impl adapted from libc++
|
||||
*/
|
||||
|
||||
template<typename>
|
||||
class Function;
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline bool func_is_not_null(T const &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool func_is_not_null(T *ptr) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
inline bool func_is_not_null(R C::*ptr) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool func_is_not_null(Function<T> const &f) {
|
||||
return !!f;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
struct FuncInvokeVoidReturnWrapper {
|
||||
template<typename ...A>
|
||||
static R call(A &&...args) {
|
||||
return func_invoke(std::forward<A>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FuncInvokeVoidReturnWrapper<void> {
|
||||
template<typename ...A>
|
||||
static void call(A &&...args) {
|
||||
func_invoke(std::forward<A>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class FuncBase;
|
||||
|
||||
template<typename R, typename ...A>
|
||||
class FuncBase<R(A...)> {
|
||||
FuncBase(FuncBase const &);
|
||||
FuncBase &operator=(FuncBase const &);
|
||||
public:
|
||||
FuncBase() {}
|
||||
virtual ~FuncBase() {}
|
||||
virtual FuncBase *clone() const = 0;
|
||||
virtual void clone(FuncBase *) const = 0;
|
||||
virtual void destroy() noexcept = 0;
|
||||
virtual void destroy_deallocate() noexcept = 0;
|
||||
virtual R operator()(A &&...args) = 0;
|
||||
};
|
||||
|
||||
template<typename F, typename A, typename AT>
|
||||
class FuncCore;
|
||||
|
||||
template<typename F, typename A, typename R, typename ...AT>
|
||||
class FuncCore<F, A, R(AT...)>: public FuncBase<R(AT...)> {
|
||||
CompressedPair<F, A> f_stor;
|
||||
public:
|
||||
explicit FuncCore(F &&f):
|
||||
f_stor(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(std::move(f)),
|
||||
std::forward_as_tuple()
|
||||
)
|
||||
{}
|
||||
|
||||
explicit FuncCore(F const &f, A const &a):
|
||||
f_stor(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(f),
|
||||
std::forward_as_tuple(a)
|
||||
)
|
||||
{}
|
||||
|
||||
explicit FuncCore(F const &f, A &&a):
|
||||
f_stor(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(f),
|
||||
std::forward_as_tuple(std::move(a))
|
||||
)
|
||||
{}
|
||||
|
||||
explicit FuncCore(F &&f, A &&a):
|
||||
f_stor(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(std::move(f)),
|
||||
std::forward_as_tuple(std::move(a))
|
||||
)
|
||||
{}
|
||||
|
||||
virtual FuncBase<R(AT...)> *clone() const;
|
||||
virtual void clone(FuncBase<R(AT...)> *) const;
|
||||
virtual void destroy() noexcept;
|
||||
virtual void destroy_deallocate() noexcept;
|
||||
virtual R operator()(AT &&...args);
|
||||
};
|
||||
|
||||
template<typename F, typename A, typename R, typename ...AT>
|
||||
FuncBase<R(AT...)> *FuncCore<F, A, R(AT...)>::clone() const {
|
||||
using AA = AllocatorRebind<A, FuncCore>;
|
||||
AA a(f_stor.second());
|
||||
using D = AllocatorDestructor<AA>;
|
||||
Box<FuncCore, D> hold(a.allocate(1), D(a, 1));
|
||||
::new(hold.get()) FuncCore(f_stor.first(), A(a));
|
||||
return hold.release();
|
||||
}
|
||||
|
||||
template<typename F, typename A, typename R, typename ...AT>
|
||||
void FuncCore<F, A, R(AT...)>::clone(FuncBase<R(AT...)> *p) const {
|
||||
::new (p) FuncCore(f_stor.first(), f_stor.second());
|
||||
}
|
||||
|
||||
template<typename F, typename A, typename R, typename ...AT>
|
||||
void FuncCore<F, A, R(AT...)>::destroy() noexcept {
|
||||
f_stor.~CompressedPair<F, A>();
|
||||
}
|
||||
|
||||
template<typename F, typename A, typename R, typename ...AT>
|
||||
void FuncCore<F, A, R(AT...)>::destroy_deallocate() noexcept {
|
||||
using AA = AllocatorRebind<A, FuncCore>;
|
||||
AA a(f_stor.second());
|
||||
f_stor.~CompressedPair<F, A>();
|
||||
a.deallocate(this, 1);
|
||||
}
|
||||
|
||||
template<typename F, typename A, typename R, typename ...AT>
|
||||
R FuncCore<F, A, R(AT...)>::operator()(AT &&...args) {
|
||||
using Invoker = FuncInvokeVoidReturnWrapper<R>;
|
||||
return Invoker::call(f_stor.first(), std::forward<AT>(args)...);
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
class Function<R(Args...)> {
|
||||
using Base = detail::FuncBase<R(Args...)>;
|
||||
AlignedStorage<3 * sizeof(void *)> p_buf;
|
||||
Base *p_f;
|
||||
|
||||
static inline Base *as_base(void *p) {
|
||||
return reinterpret_cast<Base *>(p);
|
||||
}
|
||||
|
||||
template<
|
||||
typename F,
|
||||
bool = !IsSame<F, Function> && detail::IsInvokable<F &, Args...>
|
||||
>
|
||||
struct CallableBase;
|
||||
|
||||
template<typename F>
|
||||
struct CallableBase<F, true> {
|
||||
static constexpr bool value =
|
||||
IsSame<R, void> || IsConvertible<detail::InvokeOf<F &, Args...>, R>;
|
||||
};
|
||||
template<typename F>
|
||||
struct CallableBase<F, false> {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
static constexpr bool Callable = CallableBase<F>::value;
|
||||
|
||||
public:
|
||||
using Result = R;
|
||||
|
||||
Function() noexcept: p_f(nullptr) {}
|
||||
Function(Nullptr) noexcept: p_f(nullptr) {}
|
||||
|
||||
Function(Function const &);
|
||||
Function(Function &&) noexcept;
|
||||
|
||||
template<
|
||||
typename F, typename = EnableIf<Callable<F> && !IsSame<F, Function>>
|
||||
>
|
||||
Function(F);
|
||||
|
||||
template<typename A>
|
||||
Function(AllocatorArg, A const &) noexcept: p_f(nullptr) {}
|
||||
template<typename A>
|
||||
Function(AllocatorArg, A const &, Nullptr) noexcept: p_f(nullptr) {}
|
||||
template<typename A>
|
||||
Function(AllocatorArg, A const &, Function const &);
|
||||
template<typename A>
|
||||
Function(AllocatorArg, A const &, Function &&);
|
||||
template<typename F, typename A, typename = EnableIf<Callable<F>>>
|
||||
Function(AllocatorArg, A const &, F);
|
||||
|
||||
Function &operator=(Function const &f) {
|
||||
Function(f).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Function &operator=(Function &&) noexcept;
|
||||
Function &operator=(Nullptr) noexcept;
|
||||
|
||||
template<typename F>
|
||||
EnableIf<
|
||||
Callable<Decay<F>> && !IsSame<RemoveReference<F>, Function>,
|
||||
Function &
|
||||
> operator=(F &&f) {
|
||||
Function(std::forward<F>(f)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Function();
|
||||
|
||||
void swap(Function &) noexcept;
|
||||
|
||||
explicit operator bool() const noexcept { return p_f; }
|
||||
|
||||
/* deleted overloads close possible hole in the type system */
|
||||
template<typename RR, typename ...AA>
|
||||
bool operator==(Function<RR(AA...)> &) const = delete;
|
||||
template<typename RR, typename ...AA>
|
||||
bool operator!=(Function<RR(AA...)> &) const = delete;
|
||||
|
||||
R operator()(Args ...a) const {
|
||||
return (*p_f)(std::forward<Args>(a)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
Function<R(Args...)>::Function(Function const &f) {
|
||||
if (!f.p_f) {
|
||||
p_f = nullptr;
|
||||
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
|
||||
p_f = as_base(&p_buf);
|
||||
f.p_f->clone(p_f);
|
||||
} else {
|
||||
p_f = f.p_f->clone();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
template<typename A>
|
||||
Function<R(Args...)>::Function(
|
||||
AllocatorArg, A const &, Function const &f
|
||||
) {
|
||||
if (!f.p_f) {
|
||||
p_f = nullptr;
|
||||
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
|
||||
p_f = as_base(&p_buf);
|
||||
f.p_f->clone(p_f);
|
||||
} else {
|
||||
p_f = f.p_f->clone();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
Function<R(Args...)>::Function(Function &&f) noexcept {
|
||||
if (!f.p_f) {
|
||||
p_f = nullptr;
|
||||
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
|
||||
p_f = as_base(&p_buf);
|
||||
f.p_f->clone(p_f);
|
||||
} else {
|
||||
p_f = f.p_f;
|
||||
f.p_f = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
template<typename A>
|
||||
Function<R(Args...)>::Function(
|
||||
AllocatorArg, A const &, Function &&f
|
||||
) {
|
||||
if (!f.p_f) {
|
||||
p_f = nullptr;
|
||||
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
|
||||
p_f = as_base(&p_buf);
|
||||
f.p_f->clone(p_f);
|
||||
} else {
|
||||
p_f = f.p_f;
|
||||
f.p_f = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
template<typename F, typename>
|
||||
Function<R(Args...)>::Function(F f): p_f(nullptr) {
|
||||
if (!detail::func_is_not_null(f)) {
|
||||
return;
|
||||
}
|
||||
using FF = detail::FuncCore<F, Allocator<F>, R(Args...)>;
|
||||
if ((sizeof(FF) <= sizeof(p_buf)) && IsNothrowCopyConstructible<F>) {
|
||||
p_f = ::new(static_cast<void *>(&p_buf)) FF(std::move(f));
|
||||
return;
|
||||
}
|
||||
using AA = Allocator<FF>;
|
||||
AA a;
|
||||
using D = detail::AllocatorDestructor<AA>;
|
||||
Box<FF, D> hold(a.allocate(1), D(a, 1));
|
||||
::new(hold.get()) FF(std::move(f), Allocator<F>(a));
|
||||
p_f = hold.release();
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
template<typename F, typename A, typename>
|
||||
Function<R(Args...)>::Function(AllocatorArg, A const &a, F f):
|
||||
p_f(nullptr)
|
||||
{
|
||||
if (!detail::func_is_not_null(f)) {
|
||||
return;
|
||||
}
|
||||
using FF = detail::FuncCore<F, A, R(Args...)>;
|
||||
using AA = AllocatorRebind<A, FF>;
|
||||
AA aa(a);
|
||||
if (
|
||||
(sizeof(FF) <= sizeof(p_buf)) && IsNothrowCopyConstructible<F> &&
|
||||
IsNothrowCopyConstructible<AA>
|
||||
) {
|
||||
p_f = ::new(static_cast<void *>(&p_buf)) FF(std::move(f), A(aa));
|
||||
return;
|
||||
}
|
||||
using D = detail::AllocatorDestructor<AA>;
|
||||
Box<FF, D> hold(aa.allocate(1), D(aa, 1));
|
||||
::new(hold.get()) FF(std::move(f), A(aa));
|
||||
p_f = hold.release();
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
Function<R(Args...)> &Function<R(Args...)>::operator=(Function &&f)
|
||||
noexcept
|
||||
{
|
||||
if (static_cast<void *>(p_f) == &p_buf) {
|
||||
p_f->destroy();
|
||||
} else if (p_f) {
|
||||
p_f->destroy_deallocate();
|
||||
}
|
||||
if (f.p_f == nullptr) {
|
||||
p_f = nullptr;
|
||||
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
|
||||
p_f = as_base(&p_buf);
|
||||
f.p_f->clone(p_f);
|
||||
} else {
|
||||
p_f = f.p_f;
|
||||
f.p_f = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
Function<R(Args...)> &Function<R(Args...)>::operator=(Nullptr) noexcept {
|
||||
if (static_cast<void *>(p_f) == &p_buf) {
|
||||
p_f->destroy();
|
||||
} else if (p_f) {
|
||||
p_f->destroy_deallocate();
|
||||
}
|
||||
p_f = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
Function<R(Args...)>::~Function() {
|
||||
if (static_cast<void *>(p_f) == &p_buf) {
|
||||
p_f->destroy();
|
||||
} else if (p_f) {
|
||||
p_f->destroy_deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
void Function<R(Args...)>::swap(Function &f) noexcept {
|
||||
if (
|
||||
(static_cast<void *>(p_f) == &p_buf) &&
|
||||
(static_cast<void *>(f.p_f) == &f.p_buf)
|
||||
) {
|
||||
/* both in small storage */
|
||||
AlignedStorage<sizeof(p_buf)> tmpbuf;
|
||||
Base *t = as_base(&tmpbuf);
|
||||
p_f->clone(t);
|
||||
p_f->destroy();
|
||||
p_f = nullptr;
|
||||
f.p_f->clone(as_base(&p_buf));
|
||||
f.p_f->destroy();
|
||||
f.p_f = nullptr;
|
||||
p_f = as_base(&p_buf);
|
||||
t->clone(as_base(&f.p_buf));
|
||||
t->destroy();
|
||||
f.p_f = as_base(&f.p_buf);
|
||||
} else if (static_cast<void *>(p_f) == &p_buf) {
|
||||
/* ours in small storage */
|
||||
p_f->clone(as_base(&f.p_buf));
|
||||
p_f->destroy();
|
||||
p_f = f.p_f;
|
||||
f.p_f = as_base(&f.p_buf);
|
||||
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
|
||||
/* the other in small storage */
|
||||
f.p_f->clone(as_base(&p_buf));
|
||||
f.p_f->destroy();
|
||||
f.p_f = p_f;
|
||||
p_f = as_base(&p_buf);
|
||||
} else {
|
||||
detail::swap_adl(p_f, f.p_f);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
inline bool operator==(Function<R(Args...)> const &f, Nullptr) noexcept {
|
||||
return !f;
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
inline bool operator==(Nullptr, Function<R(Args...)> const &f) noexcept {
|
||||
return !f;
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
inline bool operator!=(Function<R(Args...)> const &f, Nullptr) noexcept {
|
||||
return bool(f);
|
||||
}
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
inline bool operator!=(Nullptr, Function<R(Args...)> const &f) noexcept {
|
||||
return bool(f);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename F>
|
||||
struct DcLambdaTypes: DcLambdaTypes<decltype(&F::operator())> {};
|
||||
|
||||
template<typename C, typename R, typename ...A>
|
||||
struct DcLambdaTypes<R (C::*)(A...) const> {
|
||||
using Ptr = R (*)(A...);
|
||||
using Obj = Function<R(A...)>;
|
||||
};
|
||||
|
||||
template<typename FF>
|
||||
static char dc_func_test(typename DcLambdaTypes<FF>::Ptr);
|
||||
template<typename FF>
|
||||
static int dc_func_test(...);
|
||||
|
||||
template<typename F>
|
||||
constexpr bool DcFuncTest = (sizeof(dc_func_test<F>(declval<F>())) == 1);
|
||||
|
||||
template<typename F, bool = DcFuncTest<F>>
|
||||
struct DcFuncTypeObjBase {
|
||||
using Type = typename DcLambdaTypes<F>::Obj;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct DcFuncTypeObjBase<F, true> {
|
||||
using Type = typename DcLambdaTypes<F>::Ptr;
|
||||
};
|
||||
|
||||
template<typename F, bool =
|
||||
IsDefaultConstructible<F> && IsMoveConstructible<F>
|
||||
>
|
||||
struct DcFuncTypeObj {
|
||||
using Type = typename DcFuncTypeObjBase<F>::Type;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct DcFuncTypeObj<F, true> {
|
||||
using Type = F;
|
||||
};
|
||||
|
||||
template<typename F, bool = IsClass<F>>
|
||||
struct DcFuncType {
|
||||
using Type = F;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct DcFuncType<F, true> {
|
||||
using Type = typename DcFuncTypeObj<F>::Type;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
using FunctionMakeDefaultConstructible = typename detail::DcFuncType<F>::Type;
|
||||
|
||||
} /* namespace ostd */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,9 +52,9 @@ inline void swap(T &a, T &b) noexcept(noexcept(detail::swap_fb(a, b))) {
|
|||
}
|
||||
|
||||
template<typename T, Size N>
|
||||
inline void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))) {
|
||||
inline void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(ostd::swap(*a, *b))) {
|
||||
for (Size i = 0; i < N; ++i) {
|
||||
swap(a[i], b[i]);
|
||||
ostd::swap(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ namespace detail {
|
|||
namespace adl_swap {
|
||||
using ostd::swap;
|
||||
template<typename T>
|
||||
inline void swap_adl(T &a, T &b) noexcept(noexcept(swap(a, b))) {
|
||||
swap(a, b);
|
||||
inline void swap_adl(T &a, T &b) noexcept(noexcept(ostd::swap(a, b))) {
|
||||
ostd::swap(a, b);
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in a new issue