AuROXTL/Include/auROXTL/auSwapExchangeUtils.hpp
2023-04-17 04:30:17 +01:00

67 lines
1.6 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auSwapExchangeUtils.hpp
Date: 2022-3-27
Author: Reece
***/
#pragma once
namespace __audetail
{
template <class T>
struct AuHasSwap
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void(C:: *)(C &)>(&C::Swap)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
template <class T>
struct AuHasswap
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void(C:: *)(C &)>(&C::swap)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
template <class T>
constexpr inline bool AuAuHasSwap_v = AuHasSwap<T>::type::value;
template <class T>
constexpr inline bool AuAuHasswap_v = AuHasswap<T>::type::value;
}
template <class T, class U = T>
inline T AuExchange(T &obj, U &&newValue)
{
T oldValue = AuMove(obj);
obj = AuForward<U>(newValue);
return oldValue;
}
#if !defined(AURORA_RUNTIME_SWAP) && !defined(AURORA_SWAP_COCKBLOCK)
#define AURORA_RUNTIME_SWAP std::swap
#endif
template <class T>
inline void AuSwap(T &a, T &b)
{
if constexpr (__audetail::AuAuHasSwap_v<T>)
{
a.Swap(b);
return;
}
if constexpr (__audetail::AuAuHasswap_v<T>)
{
a.swap(b);
return;
}
#if defined(AURORA_RUNTIME_SWAP)
AURORA_RUNTIME_SWAP(a, b);
return;
#else
static_assert(false, "cannot swap T");
#endif
}