vendredi 30 janvier 2015

Removing the first specified type found from a nested pack

For example,



using NestedPack = Pack<long, char, double, Pack<long, int, short, int>, char, int>;


Then



RemoveFirstFoundFromNestedPack<int, NestedPack>::type


is supposed to give



Pack<long, char, double, Pack<long, short, int>, char, int>


First, I took care of the case of a non-nested pack:



template <typename T> struct Identity { using type = T; };

template <typename, typename, typename...> struct RemoveFirstFoundFromPackHelper;

template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromPackHelper<RemoveMe, P<>, Types...> {
using type = P<Types...>;
};

template <typename RemoveMe, template<typename...> class P, typename First, typename... Rest, typename... Types>
struct RemoveFirstFoundFromPackHelper<RemoveMe, P<First, Rest...>, Types...> : std::conditional<std::is_same<RemoveMe, First>::value,
Identity <P<Types..., Rest...>>,
RemoveFirstFoundFromPackHelper<RemoveMe, P<Rest...>, Types..., First>
>::type {};

template <typename, typename> struct RemoveFirstFoundFromPack;

template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromPack<RemoveMe, P<Types...>> : RemoveFirstFoundFromPackHelper<RemoveMe, P<Types...>> {};


This was tested to work correctly (using std::is_same). But I'm stuck with the nested case. This was my latest attempt, which gives incorrect results (though I couldn't trace why):



template <typename>
struct IsPack : std::false_type {};

template <template<typename...> class P, typename... Types>
struct IsPack<P<Types...>> : std::true_type {};

template <typename, typename, typename...> struct RemoveFirstFoundFromNestedPackHelper;

template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<>, Types...> {
using type = P<Types...>;
};

template <typename RemoveMe, template<typename...> class P, typename First, typename... Rest, typename... Types>
struct RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<First, Rest...>, Types...> : std::conditional<std::is_same<RemoveMe, First>::value,
Identity <P<Types..., Rest...>>,
typename std::conditional<IsPack<First>::value,
RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<Rest...>, Types..., RemoveFirstFoundFromNestedPackHelper<RemoveMe, First>>,
RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<Rest...>, Types..., First>
>::type
>::type {};


I know there must be a better way than this.


Of course, once this problem is solved, then removing all instances of the specified type found from the nested pack should be easy (I've already done that for the non-nested case).


Aucun commentaire:

Enregistrer un commentaire