पर यह इस के लिए template
metaprogramming के एक से अधिक इंजीनियर सा है कार्य।
#include <utility>
#include <type_traits>
template<typename... Ts> struct pack {};
template<std::size_t index, typename Pack, typename=void> struct nth_type;
template<typename T0, typename... Ts>
struct nth_type<0, pack<T0, Ts...>, void> { typedef T0 type; };
template<std::size_t index, typename T0, typename... Ts>
struct nth_type<index, pack<T0, Ts...>, typename std::enable_if<(index>0)>::type>:
nth_type<index-1, pack<Ts...>>
{};
template<std::size_t... s> struct seq {};
template<std::size_t n, std::size_t... s>
struct make_seq:make_seq<n-1, n-1, s...> {};
template<std::size_t... s>
struct make_seq<0,s...> {
typedef seq<s...> type;
};
template<typename T, typename Pack> struct conc_pack { typedef pack<T> type; };
template<typename T, typename... Ts> struct conc_pack<T, pack<Ts...>> { typedef pack<T, Ts...> type; };
template<std::size_t n, typename Seq> struct append;
template<std::size_t n, std::size_t... s>
struct append<n, seq<s...>> {
typedef seq<n, s...> type;
};
template<typename S0, typename S1> struct conc;
template<std::size_t... s0, std::size_t... s1>
struct conc<seq<s0...>, seq<s1...>>
{
typedef seq<s0..., s1...> type;
};
template<typename T, typename=void> struct value_exists:std::false_type {};
template<typename T> struct value_exists<T,
typename std::enable_if< std::is_same<decltype(T::value),decltype(T::value)>::value >::type
>:std::true_type {};
template<typename T, typename=void> struct result_exists:std::false_type {};
template<typename T> struct result_exists<T,
typename std::enable_if< std::is_same<typename T::result,typename T::result>::value >::type
>:std::true_type {};
template<template<std::size_t>class filter, typename Seq, typename=void>
struct filter_seq { typedef seq<> type; };
template<template<std::size_t>class filter, std::size_t s0, std::size_t... s>
struct filter_seq<filter, seq<s0, s...>, typename std::enable_if<value_exists<filter<s0>>::value>::type>
: append< filter<s0>::value, typename filter_seq<filter, seq<s...>>::type >
{};
template<template<std::size_t>class filter, std::size_t s0, std::size_t... s>
struct filter_seq<filter, seq<s0, s...>, typename std::enable_if<!value_exists<filter<s0>>::value && result_exists<filter<s0>>::value>::type>
: conc< typename filter<s0>::result, typename filter_seq<filter, seq<s...>>::type >
{};
template<template<std::size_t>class filter, std::size_t s0, std::size_t... s>
struct filter_seq<filter, seq<s0, s...>, typename std::enable_if<!value_exists<filter<s0>>::value && !result_exists<filter<s0>>::value>::type>
: filter_seq<filter, seq<s...>>
{};
template<typename Seq, typename Pack>
struct remap_pack {
typedef pack<> type;
};
template<std::size_t s0, std::size_t... s, typename Pack>
struct remap_pack< seq<s0, s...>, Pack >
{
typedef typename conc_pack< typename nth_type<s0, Pack>::type, typename remap_pack< seq<s...>, Pack >::type >::type type;
};
template<typename Pack>
struct get_indexes { typedef seq<> type; };
template<typename... Ts>
struct get_indexes<pack<Ts...>> {
typedef typename make_seq< sizeof...(Ts) >::type type;
};
template<std::size_t n>
struct filter_zero_out { enum{ value = n }; };
template<>
struct filter_zero_out<0> {};
template<std::size_t n>
struct filter_zero_out_b { typedef seq<n> result; };
template<>
struct filter_zero_out_b<0> { typedef seq<> result; };
#include <iostream>
int main() {
typedef pack< int, double, char > pack1;
typedef pack< double, char > pack2;
typedef filter_seq< filter_zero_out, typename get_indexes<pack1>::type >::type reindex;
typedef filter_seq< filter_zero_out_b, typename get_indexes<pack1>::type >::type reindex_b;
typedef typename remap_pack< reindex, pack1 >::type pack2_clone;
typedef typename remap_pack< reindex_b, pack1 >::type pack2_clone_b;
std::cout << std::is_same< pack2, pack2_clone >::value << "\n";
std::cout << std::is_same< pack2, pack2_clone_b >::value << "\n";
}
यहाँ हम एक प्रकार pack
कि प्रकार के एक मनमाना सूची रखती है: यह एक फिल्टर template
के माध्यम से मनमाने ढंग से पुन: क्रमित/दोहराव/एक tuple
के प्रकार पर इन्हें हटाने ऐसा करने की क्षमता भी शामिल है। tuple
और pack
के बीच कैसे स्थानांतरित करें के लिए @LucTouraille का साफ जवाब देखें।
seq
इंडेक्स का अनुक्रम रखता है। remap_pack
seq
और pack
लेता है, और मूल pack
के nth तत्व को पकड़कर परिणामस्वरूप pack
बनाता है।
filter_seq
एक template<size_t>
functor और एक seq
लेता है, और seq
के तत्वों फिल्टर करने के लिए functor उपयोग करता है। मज़ेदार ::value
प्रकार size_t
या ::result
प्रकार seq<...>
या न तो, एक-से-एक या एक से कई मल्टीकर्स को अनुमति दे सकता है।
कुछ अन्य सहायक काम करता है, की तरह conc
, append
, conc_pack
, get_indexes
, make_seq
, nth_type
दौर बातें बाहर।
मैं जो एक ::value
आधारित फिल्टर कि 0 निकाल देता है, और filter_zero_out_b
जो जो `tuple` इन दो प्रकार लेता है एक ::result
आधारित फिल्टर वह भी निकाल देता है 0.
अधिभार' ऑपरेटर = ', है
filter_zero_out
साथ यह परीक्षण किया रों? –कार्यान्वयन की त्वरित रूपरेखा इसलिए उत्तर देने के लिए क्षमता * और समय * के साथ कोई ऐसा कर सकता है :): 0 के बिना इंडेक्स पैक करें, और विविधता '' 'make_tuple' पर बढ़ाएं। –
@meh: यह काम नहीं करेगा क्योंकि मुझे वस्तुओं में नहीं, प्रकारों में दिलचस्पी है। – cschwan