TSignedIntType 和 TUnsignedIntType

作者:PP屁屁


用途

  • TSignedIntType
    • 用来根据字节数,传出自己想要的int类型
  • TUnsignedIntType
    • 用来根据字节数,传出自己想要的unsigned int类型

目的

  • 基于不同平台的C++运行库相关的API进行封装,以下为Windows举例
  • C++运行库底层确实对 不同位数 的数据给予了不同的 API
  • Unreal 对其做了 跨平台的封装
  • 位于 intrin0.inl.h 文件 150行

__MACHINEWVMPURE(long _InterlockedCompareExchange(long volatile * _Destination, long _Exchange, long _Comparand))
__MACHINE(short _InterlockedCompareExchange16(short volatile * _Destination, short _Exchange, short _Comparand))
__MACHINEARM_ARM64(short _InterlockedCompareExchange16_acq(short volatile * _Destination, short _Exchange, short _Comparand))
__MACHINEARM_ARM64(short _InterlockedCompareExchange16_nf(short volatile * _Destination, short _Exchange, short _Comparand))
__MACHINEARM_ARM64(short _InterlockedCompareExchange16_rel(short volatile * _Destination, short _Exchange, short _Comparand))
__MACHINE(__int64 _InterlockedCompareExchange64(__int64 volatile * _Destination, __int64 _Exchange, __int64 _Comparand))
__MACHINEARM_ARM64(__int64 _InterlockedCompareExchange64_acq(__int64 volatile * _Destination, __int64 _Exchange, __int64 _Comparand))
__MACHINEARM_ARM64(__int64 _InterlockedCompareExchange64_nf(__int64 volatile * _Destination, __int64 _Exchange, __int64 _Comparand))
__MACHINEARM_ARM64(__int64 _InterlockedCompareExchange64_rel(__int64 volatile * _Destination, __int64 _Exchange, __int64 _Comparand))
__MACHINE(char _InterlockedCompareExchange8(char volatile * _Destination, char _Exchange, char _Comparand))
__MACHINEARM_ARM64(char _InterlockedCompareExchange8_acq(char volatile * _Destination, char _Exchange, char _Comparand))
__MACHINEARM_ARM64(char _InterlockedCompareExchange8_nf(char volatile * _Destination, char _Exchange, char _Comparand))
__MACHINEARM_ARM64(char _InterlockedCompareExchange8_rel(char volatile * _Destination, char _Exchange, char _Comparand))

简单用法

可用于多级泛型嵌套

template<typename T>
void GetAll()
{
	TSignedIntType_T<sizeof(T)> t;
	DebugToolsNameSpace::PrintAllMessage("TSignedIntType_T<sizeof(MyTestStruct)>", typeid(t).name());
	TUnsignedIntType_T<sizeof(T)> t;
	DebugToolsNameSpace::PrintAllMessage("TSignedIntType_T<sizeof(MyTestStruct)>", typeid(t).name());
}
void main()
{
	GetAll<double>();
}


实际使用场景(代码抽取)

  • 实际使用场景在Unreal内置的原子操作里面有使用
  • 基于不同平台的C++运行库相关的API进行封装
    intType.h
//intType.h
    template <int NumBytes>
    struct TSignedIntType
    {
    };

    template <> struct TSignedIntType<1> { using Type = int8; };
    template <> struct TSignedIntType<2> { using Type = int16; };
    template <> struct TSignedIntType<4> { using Type = int32; };
    template <> struct TSignedIntType<8> { using Type = int64; };

    /**
    * Helper for TSignedIntType which expands out to the nested Type.
    */
    template <int NumBytes>
    using TSignedIntType_T = typename TSignedIntType<NumBytes>::Type;




Atomic.h 48行

//Atomic.h 48行
	template <typename T>
	using TUnderlyingIntegerType_T = TSignedIntType_T<sizeof(T)>;

Atomic.h 68行

//Atomic.h 68行
	template <typename T>
	FORCEINLINE T Load(const volatile T* Element)
	{
		auto Result = FPlatformAtomics::AtomicRead((volatile TUnderlyingIntegerType_T<T>*)Element);
		return *(const T*)&Result;
	}


源码分析

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

/**
 * Type trait which yields a signed integer type of a given number of bytes.
 * If there is no such type, the Type member type will be absent, allowing it to be used in SFINAE contexts.
 */
template <int NumBytes>
struct TSignedIntType
{
};

template <> struct TSignedIntType<1> { using Type = int8; };
template <> struct TSignedIntType<2> { using Type = int16; };
template <> struct TSignedIntType<4> { using Type = int32; };
template <> struct TSignedIntType<8> { using Type = int64; };

/**
 * Helper for TSignedIntType which expands out to the nested Type.
 */
template <int NumBytes>
using TSignedIntType_T = typename TSignedIntType<NumBytes>::Type;


/**
 * Type trait which yields an unsigned integer type of a given number of bytes.
 * If there is no such type, the Type member type will be absent, allowing it to be used in SFINAE contexts.
 */
template <int NumBytes>
struct TUnsignedIntType
{
};

template <> struct TUnsignedIntType<1> { using Type = uint8; };
template <> struct TUnsignedIntType<2> { using Type = uint16; };
template <> struct TUnsignedIntType<4> { using Type = uint32; };
template <> struct TUnsignedIntType<8> { using Type = uint64; };

/**
 * Helper for TUnsignedIntType which expands out to the nested Type.
 */
template <int NumBytes>
using TUnsignedIntType_T = typename TUnsignedIntType<NumBytes>::Type;
  1. TSignedIntTypeTUnsignedIntType 通过对传入的模板参数的 具体占用字节数 进行特化特化出了4种类型
  2. 其实我们可以看到 Using 的一种实际做法在 泛型编程 中,可以将起别名的行为用来对被起别名的类型进行行为修改。
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐