рдЯрд╛рдЗрдкрд▓рд┐рд╕реНрдЯ рдФрд░ рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА

рдореИрдВ рдЕрдВрдд рдореЗрдВ рдЪрд╛рд╣рддрд╛ рдерд╛ (!) variadic templates



рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рдЕрднреА рднреА 10 рд╡реАрдВ рд╕реНрдЯреВрдбрд┐рдпреЛ рд╕реЗ рдмрдВрдзрд╛ рд╣реБрдЖ рд╣реВрдВ, рдЬрд╣рд╛рдВ рдЗрд╕рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдирд╣реАрдВ рд╣реИред рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдпрд╣ рдирд╣реАрдВ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╡реЗрд░рд┐рдПрдбрд┐рдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдХрд╣рд╛рдВ рддрдХ тАЛтАЛрдмреЗрдХрд╛рд░ рд╣реИ, рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЧрдИ рдХрд┐ рдЯрд╛рдЗрдкреЗрд▓рд┐рд╕реНрдЯ рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛ред рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрднреА рднреА рдирд╣реАрдВ рдЬрд╛рдирддреЗ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реИ, рдореИрдВ рд░рд╛рд╕реНрддреЗ рдореЗрдВ рд╕рдордЭрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛, рдФрд░ рдЬреЛ рд▓реЛрдЧ рдКрдм рдЧрдП рд╣реИрдВ - рддреБрд░рдВрдд рдиреАрдЪреЗ рд╕реНрдХреНрд░реЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - Typelist



рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЯрд┐рдХ-рдЯреИрдХ-рдЯреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВред

рддреЛ TypeList



:



TypeList
 namespace internal { struct Void { }; } // internal template<typename ...Args> struct TypeList { typedef internal::Void Head; typedef internal::Void Tail; }; typedef TypeList<> EmptyTypeList; template<typename H, typename ...T> struct TypeList<H, T...> { typedef H Head; typedef TypeList<T...> Tail; };
      
      







рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ TypeList



рдПрдХ "рд╣реЗрдб" рдФрд░ рдПрдХ "рдЯреЗрд▓" рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИред рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

 typedef TypeList<float, double, long double> floating_point_types;
      
      





рдкрд╣рд▓реЗ, C ++ 11 рдХреЗ рдмрд┐рдирд╛, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рдерд╛:

рдкреБрд░рд╛рдирд╛ рдЯрд╛рдЗрдкрд┐рд╕реНрдЯ
 template <class H, class T> struct typelist { typedef H head; typedef T tail; }; typedef typelist<float, typelist<double, long double> > floating_point_types;
      
      





рдФрд░ рдореИрдХреНрд░реЛрдЬрд╝ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:

 #define TYPELIST_1(T1) typelist<T1, null_typelist> #define TYPELIST_2(T1, T2) typelist<T1, TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) typelist<T1, TYPELIST_2(T2, T3) > ... #define TYPELIST_50...
      
      







рд▓реЗрдХрд┐рди рдЕрдм, variadic templates



рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЖрдк рд╕реВрдЪреА рдореЗрдВ рдореИрдХреНрд░реЛ рдФрд░ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рд╕реАрдорд╛ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рджрд┐рд▓рдЪрд╕реНрдк рдпрд╣ рд╣реИ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реИ, рдЙрд╕ рдкрд░ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдХреИрд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ рдФрд░ рдпрд╣ рдЖрдЦрд┐рд░ рдореЗрдВ рдХреНрдпрд╛ рджреЗрддрд╛ рд╣реИ (рдЬреЛ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рд╡рд┐рд╡рд░рдг рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдФрд░ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдЖрдзреБрдирд┐рдХ рд╕реА ++ рдбрд┐рдЬрд╛рдЗрди рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИ - рдореИрдВ рдЖрдкрдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ - рдпрд╣ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдпрд╣ 2001 рд╣реИ! )ред

рдЗрд╕рд▓рд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдореИрдВрдиреЗ рд╕рд╣рд╛рдпрдХ рдкреНрд░рдХрд╛рд░ internal::Void



рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛, рдЬреЛ рд╕рд┐рдЧреНрдирд▓ рдзреНрд╡рдЬ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдФрд░ рдХрд╣реЗрдЧрд╛ рдХрд┐ рдкреНрд░рдХрд╛рд░ рдХреА рд╕реВрдЪреА рдЦрд╛рд▓реА рд╣реИ (рдХрдо рд╕реЗ рдХрдо рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдХреБрдЫ рднреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ: TypeList<>



, рдпрд╛ рд╕реВрдЪреА рд╕реЗ рдЬрдм рд╕рднреА рдЖрдЗрдЯрдо рд╣рдЯрд╛рдП рдЧрдП)ред рдЪрд▓рд┐рдП рд╢реБрд░реВ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:

IsEmpty



IsEmpty
 template<typename TL> struct IsEmpty : std::true_type { }; template<> struct IsEmpty<TypeList<internal::Void, internal::Void>> : std::true_type { }; template<typename ...Args> struct IsEmpty<TypeList<Args...>> : std::integral_constant<bool, std::is_same<typename TypeList<Args...>::Head, internal::Void>::value && IsEmpty<typename TypeList<Args...>::Tail>::value> { };
      
      







рдпрд╣рд╛рдВ рдЖрдк рд▓рдЧрднрдЧ рд╕рднреА рдЪреАрдЬреЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдореЗрдВ рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдкрд╣рд▓реЗ "рдмреИрдХрдмреЛрди" рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ: IsEmpty



рдкреНрд░рдХрд╛рд░ рдХреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╕реЗ рдкреИрд░рд╛рдореАрдЯрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдпрд╣ рдПрдХ "рдлрд╝рдВрдХреНрд╢рди" рд╣реИ рдЬреЛ рдПрдХ рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдЯрд╛рдЗрдк TL



рдЕрд░реНрде рд╣реИ "рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░", рд╣рдо рдЦрд╛рд▓реА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдПрдХ рдкреВрд░реНрдг рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХрд░рддреЗ рд╣реИрдВ: TypeList<internal::Void, internal::Void>



(рдпрд╣ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ TypeList<>



рдпрд╛, рдмрд╕ рдЙрд╕рдХреЗ рд▓рд┐рдП, рдореИрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдкреНрд░рдХрд╛рд░ EmptyTypeList



) рдФрд░ рдПрдХ рдЖрдВрд╢рд┐рдХ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдЬреЛ рдХрд╛рдо рдХрд░рддреА рд╣реИ - "рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдПред" рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдорд╛рд░реЗ "рдлрд╝рдВрдХреНрд╢рди" рдХреЛ рдХреЗрд╡рд▓ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдПрд╕рдЯреАрдбреА рдЬреИрд╕реА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЪреАрдЬреЗрдВ :: рдЗрдВрдЯреАрдЧреНрд░рд▓_рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ рдирдП рдорд╛рдирдХ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреА рд╣реИрдВ, рдЬреЛ рдЬреАрд╡рди рдХреЛ рдмрд╣реБрдд рд╕рд░рд▓ рдмрдирд╛рддреА рд╣реИрдВ: struct IsEmpty : std::true_type



рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ struct IsEmpty : std::true_type



, struct IsEmpty : std::true_type



рдореЗрдВ value



рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рд╕рджрд╕реНрдп, рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ typedef



рдФрд░ рдПрдХ рд░реВрдкрд╛рдВрддрд░рдг рдСрдкрд░реЗрдЯрд░ рд╣реИред

рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ?:

 typedef TypeList<int> TL1; std::cout << std::boolalpha << IsEmpty<TL1>::value << " " << IsEmpty<EmptyTypeList>() << std::endl;
      
      





рдХреНрдпрд╛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рд╣реИ, рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреА рд╣реИ:

 std::is_same<typename TypeList<Args...>::Head, internal::Void>::value && IsEmpty<typename TypeList<Args...>::Tail>::value
      
      





рд╡рд╕реНрддреБрддрдГ - "рд╕реВрдЪреА рдЦрд╛рд▓реА рд╣реИ рдпрджрд┐ рдЙрд╕рдХрд╛ рд╕рд┐рд░ рдПрдХ рд╕рд╣рд╛рдпрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬреЛ void



рдХреЛ рдирд┐рд░реВрдкрд┐рдд рдХрд░рддрд╛ void



рдФрд░ рдпрджрд┐ рдЙрд╕рдХреА рдкреВрдВрдЫ рднреА рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рд╣реИред" рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣рд╛рдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЦрд╛рд▓реА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдкреВрд░реНрдг рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХреЛ рд░реЛрдХрддрд╛ рд╣реИред

рдЕрдЧрд▓реЗ:

рд╢рд╛рдорд┐рд▓



рд╢рд╛рдорд┐рд▓
 template<typename T, typename TL> struct Contains : std::false_type { }; template<typename ...Args> struct Contains<internal::Void, Args...> : std::false_type { }; template<typename T, typename ...Args> struct Contains<T, TypeList<Args...>> : std::integral_constant<bool, std::is_same<typename TypeList<Args...>::Head, T>::value || Contains<T, typename TypeList<Args...>::Tail>::value > { };
      
      







рдпрджрд┐ рдирд┐рд░реНрдзрд╛рд░рд┐рдд T



рдЯрд╛рдЗрдк TL



рдкреНрд░рдХрд╛рд░ рдХреА рд╕реВрдЪреА рдХреЗ рдЕрдВрджрд░ рд╣реИ, рддреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:



рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; std::cout << std::boolalpha << Contains<char, TL>::value << " " << Contains<float, TypeList<double>>() << std::endl;
      
      





рджреЛрдмрд╛рд░рд╛: "рдпрджрд┐ рд╕реВрдЪреА рдХрд╛ рдкреНрд░рдореБрдЦ рд╣рдорд╛рд░реЗ рдкреНрд░рдХрд╛рд░ T



, рддреЛ T



рд╕реВрдЪреА рдХреЗ рдЕрдВрджрд░ рд╣реИ, рдЕрдиреНрдпрдерд╛, рджреЗрдЦреЗрдВ рдХрд┐ рдХреНрдпрд╛ T



рд╕реВрдЪреА рдХреА рдкреВрдВрдЫ рдкрд░ рд╣реИред"

рдЖрдВрд╢рд┐рдХ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ - рдПрдХ рдПрд╣рддрд┐рдпрд╛рддреА рдЙрдкрд╛рдп - рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдХреЛрдИ рд╣рдорд╛рд░реЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ internal::Void



?

рд▓рдВрдмрд╛рдИ



рд▓рдВрдмрд╛рдИ
 template<typename TL> struct Length : std::integral_constant<unsigned int, 0> { }; template<typename ...Args> struct Length<TypeList<Args...>> : std::integral_constant<unsigned int, IsEmpty<TypeList<Args...>>::value ? 0 : 1 + Length<typename TypeList<Args...>::Tail>::value> { };
      
      







рдпрджрд┐ рд╕реВрдЪреА рдЦрд╛рд▓реА рд╣реИ, рддреЛ рд▓рдВрдмрд╛рдИ рд╢реВрдиреНрдп рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ рдПрдХ рд╣реИ (рдХреНрдпреЛрдВрдХрд┐ "рд╣реЗрдб" рд╣реИ) + рдкреВрдВрдЫ рдХреА рд▓рдВрдмрд╛рдИ:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; std::cout << Length<TL>::value << " " << Length<EmptyTypeList>() << std::endl;
      
      





TypeAt



 template<unsigned int N, typename TL> struct TypeAt { typedef internal::Void type; };
      
      





- рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░, рд▓рдЧрднрдЧ рдПрдХ рд╕рд░рдгреА рдХреА рддрд░рд╣ред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд╣рд▓реА рдХреЙрд▓ рд╣реИ (рд╣рдо рдЯрд╛рдЗрдк N



рдХреЛ int



рдмрджрд▓рддреЗ рд╣реИрдВ):

 //template<int N, typename ...Args> //struct TypeAt<N, TypeList<Args...>> //{ // typedef typename std::conditional<N == 0, // typename TypeList<Args...>::Head, // typename TypeAt<N - 1, typename TypeList<Args...>::Tail>::type>::type type; //};
      
      





- рд╕рдм рдХреБрдЫ рдареАрдХ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди! - рдпрджрд┐ рд╕реВрдЪрдХрд╛рдВрдХ рдмрд╣реБрдд рдмрдбрд╝рд╛ рд╣реИ рддреЛ рдореБрдЭреЗ рдЪреЗрддрд╛рд╡рдиреА рджреА рдЬрд╛рдПрдЧреАред рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдпрд╣ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдорд╛рдорд▓реЗ N=-1



рд▓рд┐рдП рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рддрддреНрдХрд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП, рд╣рдо рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ рдЪрд▓рддреЗ рд╣реИрдВ:

 template<typename ...Args> struct TypeAt<0, TypeList<Args...>> { typedef typename TypeList<Args...>::Head type; }; template<unsigned int N, typename ...Args> struct TypeAt<N, TypeList<Args...>> { static_assert(N < Length<TypeList<Args...>>::value, "N is too big"); typedef typename TypeAt<N - 1, typename TypeList<Args...>::Tail>::type type; };
      
      





- рд╕рд┐рд░ рдореЗрдВ рдПрдХ рд╢реВрдиреНрдп рд╕реВрдЪрдХрд╛рдВрдХ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП - рд╣рдо рдПрдХ рд╕рд╛рде рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдХрдореА рдХрд░реЗрдВрдЧреЗ рдФрд░ "рдЦрд╛рдПрдВ" рдкреВрдВрдЫ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ (рд╣рдо рдмрд╛рдПрдВ рд╕реЗ рджрд╛рдПрдВ рдЪрд▓рддреЗ рд╣реИрдВ) рдЬрдм рддрдХ рд╣рдо рдЗрд╕реЗ рджреВрд░ рдирд╣реАрдВ рд▓реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ - рд╕реВрдЪрдХрд╛рдВрдХ рд╢реВрдиреНрдп рд╣реИ, рдФрд░ рд╡рд░реНрддрдорд╛рди рд╕рд┐рд░ рдХреЛ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ! рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

 typedef TypeList<char, short> TL2; static_assert(std::is_same<TypeAt<1, TL2>::type, short>::value, "Something wrong!");
      
      





рд╕реВрдЪреА рдЙрддреНрдкрд╛рджрди



рд╕рдВрдЪрд╛рд▓рдХ <<
 //   std::ostream& operator<<(std::ostream& ostr, EmptyTypeList) { ostr << "{}"; return ostr; } template<typename TL> void PrintTypeListHelper(TL, std::ostream& ostr) { } template<typename T> void PrintTypeListHead(T, std::ostream& ostr) { ostr << typeid(T).name(); } template<typename ...Args> void PrintTypeListHead(TypeList<Args...> tl, std::ostream& ostr) { ostr << tl; } template<typename Head, typename ...Args> void PrintTypeListHelper(TypeList<Head, Args...>, std::ostream& ostr) { PrintTypeListHead(Head(), ostr); if(!IsEmpty<TypeList<Args...>>::value) { ostr << ' '; PrintTypeListHelper<Args...>(TypeList<Args...>(), ostr); } } template<typename ...Args> std::ostream& operator<<(std::ostream& ostr, TypeList<Args...> tl) { ostr << '{'; PrintTypeListHelper(tl, ostr); ostr << '}'; return ostr; }
      
      







рдпреЗ рдХрд╛рд░реНрдп рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдирд┐рдпрдорд┐рдд рдкреНрд░рдХрд╛рд░ рдХреА рд╕реВрдЪрд┐рдпреЛрдВ рдФрд░ рдиреЗрд╕реНрдЯреЗрдб рд▓реЛрдЧреЛрдВ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддреЗ рд╣реИрдВ:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; std::cout << TL() << std::endl; typedef TypeList<TL2, double, TL2> TL10; std::cout << TL10() << std::endl;
      
      





{double float float double int char char int char}







{{char short} double {char short}}









рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЬреЛрдбрд╝реЗрдВ



рдЬреЛрдбрд╝рдирд╛, рдЬреЛрдбрд╝рдирд╛
рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдЕрдВрддрд░ рдХреЗ рд╕рд╛рде рд╕реВрдЪреА рдХреЗ рдЕрдВрдд рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп:

 template<typename TOrTL2, typename TL> struct Append { }; template<typename T, typename ...Args> struct Append<T, TypeList<Args...>> { typedef TypeList<Args..., T> type; }; template<typename ...Args1, typename ...Args2> struct Append<TypeList<Args1...>, TypeList<Args2...>> { typedef TypeList<Args2..., Args1...> type; }; template<typename T, typename TL> struct Add { }; template<typename T, typename ...Args> struct Add<T, TypeList<Args...>> { typedef TypeList<Args..., T> type; };
      
      







рдкрд╣рд▓реЗ рддрд░реНрдХ рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде Append



рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдШрдЯрдХреЛрдВ рдореЗрдВ рдПрдХ "рдЕрдкрдШрдЯрди" рд╣реЛрддрд╛ рд╣реИред рдпрд╛рдиреА:

 typedef TypeList<int> TL1; typedef TypeList<char, short> TL2; std::cout << TL1() << ", " << TL2() << std::endl; std::cout << Add<TL2, TL1>::type() << ", " << Append<TL2, TL1>::type() << std::endl;
      
      





{int}, {char short}





{int {char short}}, {int char short}





рдкрд╣рд▓реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдкрд░рд┐рдгрд╛рдо рдХреА рд▓рдВрдмрд╛рдИ 2 рд╣реИ, рдЬрдмрдХрд┐ рджреВрд╕рд░реЗ рдореЗрдВ рдпрд╣ 3 рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдШрдЯрдХреЛрдВ рдореЗрдВ "рд╡рд┐рдШрдЯрд┐рдд" рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реВрдЪреАред

RemoveAll



рдЖрдЗрдЯрдо рд╣рдЯрд╛рдПрдВ
 template<typename TOrTL2, typename TL> struct RemoveAll { }; template<typename T, typename ...Args> struct RemoveAll<T, TypeList<Args...>> { private: typedef typename RemoveAll<T, typename TypeList<Args...>::Tail>::type Removed; typedef typename TypeList<Args...>::Head Head; public: typedef typename std::conditional< std::is_same<Head, T>::value, Removed, typename Append<Removed, TypeList<Head>>::type >::type type; }; template<typename T, typename Head> struct RemoveAll<T, TypeList<Head>> { typedef typename std::conditional< std::is_same<Head, T>::value, EmptyTypeList, TypeList<Head>>::type type; }; template<typename T> struct RemoveAll<T, EmptyTypeList> { typedef EmptyTypeList type; };
      
      







рдирд┐рд╖реНрдХрд╛рд╕рди рдЗрд╕ рддрд░рд╣ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:



рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рд╣рдордиреЗ рдкреВрдВрдЫ рд╕реЗ рдкрд░рд┐рдгрд╛рдо рдирд┐рдХрд╛рд▓рд╛ рддреЛ рд╣рдордиреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреА рд╕реВрдЪреА рдореЗрдВ рд╡рд░реНрдЧреАрдХреГрдд рдХрд┐рдпрд╛, рдЬрдм рд╕рдВрдпреБрдХреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдо Append



рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╕рдореВрд╣реАрдХреГрдд рд╕реВрдЪреА рдХреЛ "рдЕрдирдЗрдВрдбреЗрдВрдб" рдХрд░рддрд╛ рд╣реИред

рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; std::cout << TL() << std::endl; std::cout << RemoveAll<char, TL>::type() << std::endl;
      
      





{double float float double int char char int char}





{double float float double int int}







рдЖрдк RemoveAll



рдХрд╛ рджреВрд╕рд░рд╛ рд╕рдВрд╕реНрдХрд░рдг рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЙрди рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рджреВрд╕рд░реА рд╕реВрдЪреА рд╕реЗ рд╣рдЯрд╛ рджреЗрдЧрд╛ рдЬреЛ рдкрд╣рд▓реЗ рдореЗрдВ рд╣реИрдВред рд▓реЗрдХрд┐рди! рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрди рд╕реВрдЪрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рдирдореЗрдВ рдЕрдиреНрдп рд╕реВрдЪрд┐рдпрд╛рдБ рд╣реИрдВ:



RemoveAll v2
 //template<typename Head2, typename ...Args1> //struct RemoveAll<TypeList<Head2>, TypeList<Args1...>> //{ // typedef typename RemoveAll<Head2, TypeList<Args1...>>::type type; //}; // //template<typename ...Args1> //struct RemoveAll<EmptyTypeList, TypeList<Args1...>> //{ // typedef TypeList<Args1...> type; //}; // //template<typename ...Args2, typename ...Args1> //struct RemoveAll<TypeList<Args2...>, TypeList<Args1...>> //{ //private: // typedef TypeList<Args2...> TL2; // typedef TypeList<Args1...> TL1; // // typedef typename RemoveAll<typename TL2::Tail, TL1>::type Removed; // typedef typename TL2::Head Head2; // //public: // typedef typename std::conditional< // Contains<Head2, Removed>::value, // typename RemoveAll<Head2, Removed>::type, // TL1 // >::type type; //};
      
      







рдПрдХ рдЙрджрд╛рд╣рд░рдг:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; typedef TypeList<char, double> TL2; std::cout << TL() << std::endl; std::cout << RemoveAll<TL2, TL>::type() << std::endl;
      
      





{double float float double int char char int char}





{float float int int}





RemoveDuplicates



RemoveDuplicates
 template<typename TL> struct RemoveDuplicates { }; template<> struct RemoveDuplicates<EmptyTypeList> { typedef EmptyTypeList type; }; template<typename ...Args> struct RemoveDuplicates<TypeList<Args...>> { private: typedef TypeList<Args...> TL; typedef typename RemoveAll<typename TL::Head, typename TL::Tail>::type HeadRemovedFromTail; typedef typename RemoveDuplicates<HeadRemovedFromTail>::type TailWithoutDuplicates; public: typedef typename Append<TailWithoutDuplicates, TypeList<typename TL::Head>>::type type; };
      
      







рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЛ рд╣рдЯрд╛рдиреЗ рд╡рд╛рд▓рд╛ рдХрд╛рд░реНрдп:



рдПрдХ рдЙрджрд╛рд╣рд░рдг:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; std::cout << TL() << std::endl; std::cout << RemoveDuplicates<TL>::type() << std::endl;
      
      





{double float float double int char char int char}





{double float int char}





рдЦреЛрдЬ



рд╕реВрдЪреА рдореЗрдВ рд╕реНрдерд┐рддрд┐ рд▓рд┐рдЦреЗрдВ
 struct Constants { typedef std::integral_constant<unsigned int, UINT_MAX> npos; }; namespace internal { template<typename T, unsigned int IndexFrom, typename TL> struct FindHelper : std::integral_constant<unsigned int, 0> { }; template<typename T, unsigned int IndexFrom> struct FindHelper<T, IndexFrom, EmptyTypeList> : std::integral_constant<unsigned int, 0> { }; template<typename T, unsigned int IndexFrom, typename ...Args> struct FindHelper<T, IndexFrom, TypeList<Args...>> : std::integral_constant<unsigned int, std::is_same<typename TypeList<Args...>::Head, T>::value ? IndexFrom : IndexFrom + 1 + FindHelper<T, IndexFrom, typename TypeList<Args...>::Tail>::value> { }; } // internal template<typename T, typename TL> struct Find { }; template<typename T> struct Find<T, EmptyTypeList> : Constants::npos { }; template<typename ...Args> struct Find<internal::Void, TypeList<Args...>> : Constants::npos { }; template<typename T, typename ...Args> struct Find<T, TypeList<Args...>> : std::integral_constant<unsigned int, Contains<T, TypeList<Args...>>::value ? internal::FindHelper<T, 0, TypeList<Args...>>::value : Constants::npos::value> { };
      
      









рдХреБрдЫ рдмрд╛рддреЗрдВ:

- Constants



- рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд▓рд┐рдПред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрд╣рддрд╛ рд╣реИ рдХрд┐ рддрддреНрд╡ рдирд╣реАрдВ рдорд┐рд▓рд╛ рдерд╛ (рдореЗрд░реЗ рд╕реНрдЯреВрдбрд┐рдпреЛ рдореЗрдВ рдХреЙрдиреНрд╕реНрдЯреИрдХреНрд╕ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП UINT_MAX



)

- internal::FindHelper



- рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдПрдХ "рдЪреАрдЬрд╝" рдЬреЛ рд╕реВрдЪреА рдореЗрдВ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЦреЛрдЬ рдХрд░рддреА рд╣реИ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ (!) рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рд╣реИ (рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд IndexFrom



рдкреИрд░рд╛рдореАрдЯрд░ - рд╕рдВрджрд░реНрдн рдХрд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдореВрд▓реНрдп, рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЪреАрдЬрд╝реЛрдВ рдкрд░ рдирд╣реАрдВ :) - рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдЬрдм рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛ рдкреВрдЫреЗрдВ рдХрд┐ рдХрд┐рд╕ рд╕реНрдерд┐рддрд┐ рд╕реЗ рдЦреЛрдЬ рд╢реБрд░реВ рдХрд░реЗрдВ)



рдлрд┐рд░ рд╕реЗ - рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИ - рдпрджрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдФрд░ рд╕реВрдЪреА рдХреЗ рдкреНрд░рдореБрдЦ рдХреЗ рдкреНрд░рдХрд╛рд░ рд╕рдорд╛рди рд╣реИрдВ - рддреЛ рд╕реВрдЪрдХрд╛рдВрдХ рд╢реВрдиреНрдп рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ 1tsu рджреНрд╡рд╛рд░рд╛ рджрд╛рдИрдВ рдУрд░ рд▓реЗ рдЬрд╛рдПрдЧрд╛ рдФрд░ рд╕реВрдЪреА рдХреА рдкреВрдВрдЫ рдХреЗ рд▓рд┐рдП рднреА рдРрд╕рд╛ рд╣реА рдХрд░реЗрдЧрд╛ред

рдПрдХ рдЙрджрд╛рд╣рд░рдг:

 typedef TypeList<double, float, float, double, int, char, char, int, char> TL; std::cout << std::boolalpha << std::is_same<TypeAt<Find<double, TL>::value, TL>::type, double>() << std::endl;
      
      







рдЯреБрдХрдбрд╝рд╛



рдЯреБрдХрдбрд╝рд╛
 namespace internal { template<unsigned int IndexBegin, unsigned int IndexEnd, typename TL> struct SliceHelper { }; template<unsigned int IndexBegin, unsigned int IndexEnd> struct SliceHelper<IndexBegin, IndexEnd, EmptyTypeList> { typedef EmptyTypeList type; }; template<unsigned int IndexBegin, typename ...Args> struct SliceHelper<IndexBegin, IndexBegin, TypeList<Args...>> { typedef TypeList<typename TypeAt<IndexBegin, TypeList<Args...>>::type> type; }; template<unsigned int IndexBegin, unsigned int IndexEnd, typename ...Args> struct SliceHelper<IndexBegin, IndexEnd, TypeList<Args...>> { private: static_assert(IndexEnd >= IndexBegin, "Invalid range"); typedef TypeList<Args...> TL; public: typedef typename Add< typename TypeAt<IndexEnd, TL>::type, typename SliceHelper<IndexBegin, IndexEnd - 1, TL>::type >::type type; }; } // internal template<unsigned int IndexBegin, unsigned int IndexAfterEnd, typename TL> struct Slice { }; template<unsigned int IndexBegin, unsigned int IndexEnd, typename ...Args> struct Slice<IndexBegin, IndexEnd, TypeList<Args...>> { typedef typename internal::SliceHelper<IndexBegin, IndexEnd, TypeList<Args...>>::type type; }; template<unsigned int Index, typename TL> struct CutTo { }; template<unsigned int Index, typename ...Args> struct CutTo<Index, TypeList<Args...>> { typedef typename Slice<0, Index, TypeList<Args...>>::type type; }; template<unsigned int Index, typename TL> struct CutFrom { }; template<unsigned int Index, typename ...Args> struct CutFrom<Index, TypeList<Args...>> { private: typedef TypeList<Args...> TL; public: typedef typename Slice<Index, Length<TL>::value - 1, TL>::type type; };
      
      







рд╕реВрдЪреА рдХрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рднрд╛рдЧ "рдХрдЯреНрд╕":




All Articles