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; };
рд╕реВрдЪреА рдХрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рднрд╛рдЧ "рдХрдЯреНрд╕":
- рд╣рдо рдЦрд╛рд▓реА рд╕реВрдЪреА рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рд▓реЗ рд╕рдХрддреЗ
- рдЬрдм рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рд╛рд░рдВрдн (
IndexBegin
) рдФрд░ рдЕрдВрдд (IndexEnd
) рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣TypeAt
рдСрдкрд░реЗрд╢рди рдХреЗ рд╕рдорд╛рди рд╣реИ
рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдорд╛ рдХреЗ рдЕрдВрдд рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реБрдП, рддрддреНрд╡ рд▓реЗ рд▓реЛ рдФрд░ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ (рдЬрд┐рд╕рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдорд╛ рдХрд╛ рдЕрдВрдд 1 рд╕реАрдпреВ рд╕реЗ рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ)
рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!