【UE4】元组(TTuple)原来是这样的
最近正好在了解UFunction的反射调用,发现用到一个东西叫元组(Tuple),方便好用,所以就花时间仔细看了看。东西虽然很简单,但分析它还是花了点时间,有点绕弯弯,理解起来有点难度,所以把分析过程记录在这里。
TTuple展开
TTuple是一个模板结构体,可以很方便的定义一块连续的内存。并且该struct中有多个按顺序的不同类型的值。如下面代码所定义:TTuple<FString, int32, int32, FString> TupleValue;当然在UE中,也经常用在不定长参数模板函数或类中。
TTuple看似很复杂,当我们在阅读先关代码时,感觉很难看懂。那也许是我们看它的角度不对。接下来,本文就带大家一起看看元组(TTuple)。
既然是模板,那就应该先搞清楚展开之后的庐山真面目。定义一个元祖变量TTuple<int32, int32, int32&, int32&> TestTuple;展开之后就变成如下代码(类名可能对应不上,只是示意作用)
对a取地址(或者&TestTuple),都是取到最终的struct首地址。可以很方便的通过内存复制、写入来操作该结构体。在前面代码中TTuple<TArgs...>InParams(Forward<TArgs>(Args)...);用不定长模板参数直接构造元组(TTuple),后面我们将看到通过这种方法初始化函数调用的入参数据。
阅读TTuple源码可以看到定义如下
Types为前面定义是传入的int32,int32,int32&,int32&,可以看到TTuple继承自TTupleBase。TTupleBase有两个模板参数,第一个为TMakeIntegerSequence<uint32,sizeof...(Types)>,第二个为Types...
通过上面代码可以看到TMakeIntegerSequence长啥子样?本质就是,通过递归的方式套用TMakeIntegerSequence,最后由TConcat将这些递归之后的内容组合在一起。T为类型uint32, N为sizeof...(Types)。在本例中N=4。
第一次调用TMakeIntegerSequence,Type变成如下结果
分别将后面两个也展开,Type变成如下结果
TMakeIntegerSequence<uint32,1>找到自己的模板后变成TIntegerSequence<uint32,0>
带入之后Type有如下变化
展开内部的TConcat
带入到上一步,Type变为
到此,TTuple的第一个模板参数全部完成,接下来就是第二个模板参数Types...,在本文的例子中展开之后分别是int32, int32, int32&, int32&
所以,得到新的struct

访问Tuple中的值
如果Tuple中只有一个元素,可以直接通过Value访问。如果有多个元素可以调用Get方法访问。这里详细看看Get方法。
需要传入index下标,指明要访问第几个元素。
可以看到关键代码就是
同样的,我们用前面的struct A : B1, B2, B3, B4{}作为例子:
所以,最后基本就是直接装换为对应的父类类型,然后获取他的Value值。这部分没有详细过一遍模板的展开过程,阅读者可以按第一部分的过程自己逐个展开、替换。
后面有机会,总结一篇反射调用UFUNCTION。(貌似里面的坑还不少)。