C++ 模板參數展開
- 一、獲取可變參數大小
- 二、通過模版循環繼承的方式來展開可變參數
- 三、改用Using去實現循環繼承
一、獲取可變參數大小
背景:
FLen<int, char, long> Len;
我想要獲取模板參數類型的總大小
template<typename T,typename ...ParamTypes>
class FLen
{
public:enum{Number = FLen<T>::Number + FLen<ParamTypes...>::Number};
};template<typename Last>
class FLen<Last>
{
public:enum{Number = sizeof(Last)};
};
思想還是類似遞歸調用的思想,只是遞歸的不是函數而是模板
int main()
{FLen<int, char, long> Len;std::cout << Len.Number << std::endl;system("pause");return 0;
}
二、通過模版循環繼承的方式來展開可變參數
最終目的是構建一個 TestIndex 類型,其模板參數是從0開始到N-1的整數序列。
template<int...>
struct TestIndex
{};template<int N,int...ParamTypes>
struct FSpawnIndex : FSpawnIndex<N - 1,N - 1,ParamTypes...>
{};template<int...ParamTypes>
struct FSpawnIndex<0,ParamTypes...>
{typedef TestIndex<ParamTypes...> Type;
};
解釋一下原理和流程
起始:FSpawnIndex<3>(此時 N=3,參數包為空)
繼承:FSpawnIndex<3> : FSpawnIndex<2,2>
在內部,參數包變為 2
下一步:FSpawnIndex<2,2> : FSpawnIndex<1,1,2>
參數包變為 1,2(注意:每次遞歸在參數包頭部添加)
下一步:FSpawnIndex<1,1,2> : FSpawnIndex<0,0,1,2>
參數包變為 0,1,2
匹配終止條件:FSpawnIndex<0,0,1,2>
定義 Type 為 TestIndex<0,1,2>
int main()
{using TestType = FSpawnIndex<3>::Type;std::cout << typeid(TestType).name() << std::endl;system("pause");return 0;
}
三、改用Using去實現循環繼承
template<int...>
struct TestIndex
{};template<int N,int...ParamTypes>
struct FSpawnIndex
{using Type = typename FSpawnIndex<N - 1, N - 1, ParamTypes...>::Type;// ↑↑↑↑↑// 這個 typename 必不可少!
};template<int...ParamTypes>
struct FSpawnIndex<0, ParamTypes...>
{typedef TestIndex<ParamTypes...> Type;
};
在 C++ 模板元編程中,typename 關鍵字在這里起著??關鍵作用??,主要用于解決??依賴名稱的解析問題??。
int main()
{using TestType = FSpawnIndex<3>::Type;std::cout << typeid(TestType).name() << std::endl;system("pause");return 0;
}
??什么是依賴名稱???
FSpawnIndex<N-1, …>::Type 是??依賴于模板參數 N 和 ParamTypes… 的名稱??
編譯器在解析模板時,無法確定 ::Type 是什么(可能是類型、靜態成員或嵌套模板)
例如以下例子
// 情況分析:
struct FSpawnIndex</*...*/> {// 可能1:Type 是類型(typedef/using)typedef ... Type;// 可能2:Type 是靜態成員static int Type;// 可能3:Type 是嵌套模板template<...> class Type;
};