首页 > 解决方案 > Loki MakeTypelist 递归模板让我很困惑

问题描述

我正在研究 loki 源代码。下面是MakeTypelist让我感到困惑的。

class NullType {};
template <class T, class U>

struct Typelist
{
    typedef T Head;
     typedef U Tail;
};
template
<
typename T1  = NullType, typename T2  = NullType, typename T3  = NullType,
typename T4  = NullType, typename T5  = NullType, typename T6  = NullType,
typename T7  = NullType, typename T8  = NullType, typename T9  = NullType,
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
 > 
struct MakeTypelist
{
private:
 typedef typename MakeTypelist
 <
  T2 , T3 , T4 , 
  T5 , T6 , T7 , 
  T8 , T9 , T10, 
  T11, T12, T13,
  T14, T15, T16, 
  T17, T18
 >
  ::Result TailResult;

public:
  typedef Typelist<T1, TailResult> Result;
};

template<>
struct MakeTypelist<>
{
  typedef NullType Result;
};

using MyType=MakeTypeList<int, unsigned int, long, unsigned long, float>

递归模板如何终止?

它无法匹配空类型版本MakeTypelist,到底它会匹配MakeTypelist<NullType, NullType, NullType, NullType .....>吗?

标签: c++

解决方案


template<> struct MakeTypelist<>由于定义了返回NullType值的特化,递归模板将终止Result

这种特化完全等同于代码的下一个变体

template<>
struct MakeTypelist<NullType, NullType, NullType, NullType, ..... /* ... 18 Times ... */>
// .......

因为如果没有提供所有或没有提供模板参数,那么所有未提供的模板参数都被认为等于默认值,即 to = NullType(参见主模板定义,它具有所有 18 个参数类型具有 default = NullType)。

为那些未提供的模板参数选择默认参数与使用具有默认参数的函数具有相同的逻辑,例如,如果你有类似的函数,void f(int a = 0, int b = 0)那么你可以用三种不同的方式调用它f()f(0)并且f(0, 0)所有的都会给出相同的结果。那些未提供的函数参数将被视为等于默认值。在模板专业化中也是如此 - 如果您不提供任何参数,即 writestruct MakeTuplelist<>那么所有 18 个参数类型将被认为是NullType因为所有 18 个参数都有 defaults = NullType,与上面带有默认参数示例的函数中的行为相同。

同样在专业化中,您可以只提供一些模板参数,其余的将被视为等于默认值,例如,template<> struct MakeTypelist<int, bool>专业化将与专业化完全相同template<> struct MakeTypelist<int, bool, NullType, NullType, ...... /* 16 NullTypes */>

并且递归终止,因为最后一个尾等于MakeTypelist<NullType, NullType, NullType, .....>which 匹配的专用版本MakeTypelist通过为 提供NullType值来减少递归Result

在线尝试!

PS。相同的 defaults-behavior 不仅适用于模板的特化,还适用于用法,您可以使用类似模板,typedef MakeTypelist<> T;或者typedef MakeTypelist<int, bool> T;在这两种情况下,其余 18 个模板参数类型将等于 defaults = NullType


推荐阅读