【发布时间】:2016-08-11 23:41:59
【问题描述】:
对一组模板整数进行排序,
template <int...> struct sequence;
int main() {
using Sequence = sequence<3,6,1,0,9,5,4,7,2,8>;
static_assert(std::is_same<
sort<int, Sequence, less_than>::type,
sequence<0,1,2,3,4,5,6,7,8,9>
>::value, "");
}
我们可以使用以下实现(在 GCC 5.3 上测试):
#include <iostream>
#include <type_traits>
namespace meta {
template <typename T, T, typename> struct prepend;
template <typename T, T Add, template <T...> class Z, T... Is>
struct prepend<T, Add, Z<Is...>> {
using type = Z<Add, Is...>;
};
template <typename T, typename Pack1, typename Pack2> struct concat;
template <typename T, template <T...> class Z, T... Ts, T... Us>
struct concat<T, Z<Ts...>, Z<Us...>> {
using type = Z<Ts..., Us...>;
};
}
template <int I, int J>
struct less_than : std::conditional<(I < J), std::true_type, std::false_type>::type {};
template <typename T, typename Pack, template <T, T> class = less_than> struct sort;
template <typename T, template <T...> class Z, template <T, T> class Comparator>
struct sort<T, Z<>, Comparator> {
using type = Z<>;
};
template <typename T, typename Pack, template<T> class UnaryPredicate> struct filter;
template <typename T, template <T...> class Z, template<T> class UnaryPredicate, T I, T... Is>
struct filter<T, Z<I, Is...>, UnaryPredicate> {
using type = typename std::conditional<UnaryPredicate<I>::value,
typename meta::prepend<T, I, typename filter<T, Z<Is...>, UnaryPredicate>::type>::type,
typename filter<T, Z<Is...>, UnaryPredicate>::type
>::type;
};
template <typename T, template <T...> class Z, template<T> class UnaryPredicate>
struct filter<T, Z<>, UnaryPredicate> {
using type = Z<>;
};
template <typename T, template <T...> class Z, T N, T... Is, template <T, T> class Comparator>
struct sort<T, Z<N, Is...>, Comparator> { // Using the quicksort method.
template <T I> struct less_than : std::integral_constant<bool, Comparator<I,N>::value> {};
template <T I> struct more_than : std::integral_constant<bool, !Comparator<I,N>::value> {};
using subsequence_less_than_N = typename filter<T, Z<Is...>, less_than>::type;
using subsequence_more_than_N = typename filter<T, Z<Is...>, more_than>::type;
using type = typename meta::concat<T, typename sort<T, subsequence_less_than_N, Comparator>::type,
typename meta::prepend<T, N, typename sort<T, subsequence_more_than_N, Comparator>::type>::type
>::type;
};
// Testing
template <int...> struct sequence;
int main() {
using Sequence = sequence<3,6,1,0,9,5,4,7,2,8>;
static_assert(std::is_same<
sort<int, Sequence, less_than>::type,
sequence<0,1,2,3,4,5,6,7,8,9>
>::value, "");
}
现在假设我们要组合几个二元谓词来进行排序。例如:
25 placed first before anything else.
16 to be placed after everything else.
Even numbers placed after all 25's, if any, have been placed (and the even numbers sorted in increasing value among themselves).
After these order on ascending last digit, except that last digit 7 appears before other last digits.
If last digits are equal, order by increasing value.
我想使用类似的东西来实现composed_sort:
template <typename T, T, T, template <T, T> class...> struct composed_binary_predicates;
template <typename T, T A, T B, template <T, T> class Comparator, template <T, T> class... Rest>
struct composed_binary_predicates<T, A, B, Comparator, Rest...> : std::conditional_t<
Comparator<A,B>::value,
std::true_type,
std::conditional_t<
Comparator<B,A>::value,
std::false_type,
composed_binary_predicates<T, A, B, Rest...>
>
> {};
template <typename T, T A, T B, template <T, T> class Comparator>
struct composed_binary_predicates<T, A, B, Comparator> : Comparator<A,B> {};
所以我们使用了一组二进制谓词。如果第一个Comparator 有Comparator<A,B>::value == true,则值为真,如果Comparator<B,A>::value == true,则值为假,否则检查下一个谓词,依此类推。这种二元谓词的组合将用于执行排序。所以sort本身我尝试修改为以下内容:
template <typename T, typename Sequence,
template <typename U, U, U, template <U,U> class...> class Comparator,
template <T, T> class... Preds> struct composed_sort;
template <typename T, template <T...> class Z, T N, T... Is, template <typename U, U, U, template <U,U> class...> class Comparator, template <T, T> class... Preds>
struct composed_sort<T, Z<N, Is...>, Comparator, Preds...> {
template <T I> struct less_than : std::integral_constant<bool, Comparator<T,I,N, Preds...>::value> {};
template <T I> struct more_than : std::integral_constant<bool, !Comparator<T,I,N, Preds...>::value> {};
using subsequence_less_than_N = typename filter<T, Z<Is...>, less_than>::type;
using subsequence_more_than_N = typename filter<T, Z<Is...>, more_than>::type;
using type = typename meta::concat<T, typename composed_sort<T, subsequence_less_than_N, Comparator, Preds...>::type,
typename meta::prepend<T, N, typename composed_sort<T, subsequence_more_than_N, Comparator, Preds...>::type>::type
>::type;
};
然后可以用作
composed_sort<int, Sequence, composed_binary_predicates, Predicates...>::type
但 GCC 5.3 出现内部编译器错误,因此无法处理代码。是否有解决方法或更简单的实现来完成这项工作?
【问题讨论】:
标签: c++ sorting templates c++11 variadic-templates