C++模板应用示例
2020/12
21
12:12
// microsoft stl
// STRUCT TEMPLATE remove_reference
template <class _Ty>
struct remove_reference {
using type = _Ty;
using _Const_thru_ref_type = const _Ty;
};
template <class _Ty>
struct remove_reference<_Ty&> {
using type = _Ty;
using _Const_thru_ref_type = const _Ty&;
};
template <class _Ty>
struct remove_reference<_Ty&&> {
using type = _Ty;
using _Const_thru_ref_type = const _Ty&&;
};
template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;
// epic unreal
/**
* TRemoveReference<type> will remove any references from a type.
*/
template <typename T> struct TRemoveReference { typedef T Type; };
template <typename T> struct TRemoveReference<T& > { typedef T Type; };
template <typename T> struct TRemoveReference<T&&> { typedef T Type; };
/**
* Removes one level of pointer from a type, e.g.:
*
* TRemovePointer< int32 >::Type == int32
* TRemovePointer< int32* >::Type == int32
* TRemovePointer< int32**>::Type == int32*
* TRemovePointer<const int32* >::Type == const int32
*/
template <typename T> struct TRemovePointer { typedef T Type; };
template <typename T> struct TRemovePointer<T*> { typedef T Type; };
/**
* MoveTemp will cast a reference to an rvalue reference.
* This is UE's equivalent of std::move except that it will not compile when passed an rvalue or
* const object, because we would prefer to be informed when MoveTemp will have no effect.
*/
template <typename T>
FORCEINLINE typename TRemoveReference<T>::Type&& MoveTemp(T&& Obj)
{
typedef typename TRemoveReference<T>::Type CastType;
// Validate that we're not being passed an rvalue or a const object - the former is redundant, the latter is almost certainly a mistake
static_assert(TIsLValueReferenceType<T>::Value, "MoveTemp called on an rvalue");
static_assert(!TAreTypesEqual<CastType&, const CastType&>::Value, "MoveTemp called on a const object");
return (CastType&&)Obj;
}
/**
* MoveTemp will cast a reference to an rvalue reference.
* This is UE's equivalent of std::move. It doesn't static assert like MoveTemp, because it is useful in
* templates or macros where it's not obvious what the argument is, but you want to take advantage of move semantics
* where you can but not stop compilation.
*/
template <typename T>
FORCEINLINE typename TRemoveReference<T>::Type&& MoveTempIfPossible(T&& Obj)
{
typedef typename TRemoveReference<T>::Type CastType;
return (CastType&&)Obj;
}