【发布时间】:2016-07-27 17:27:22
【问题描述】:
当包具有所有不同类型时,我已经编写了一个工作代码来计算包的 P(N,R),例如
PermutationN<2, P<int, char, bool>>
将成为
P< P<int, char>, P<int, bool>, P<char, int>, P<char, bool>, P<bool, int>, P<bool, char> >
但是当有重复元素时,我会得到错误的结果。例如,
PermutationN<2, P<int, int, char>>
应该是
P< P<int, int>, P<int, char>, P<char, int> >
这是我在所有类型都不同时的工作代码。我坚持如何调整它,以便在包中有重复类型时给出正确的结果。任何帮助将不胜感激。
#include <iostream>
#include <type_traits>
template <typename, typename> struct Merge;
template <template <typename...> class P, typename... Ts, typename... Us>
struct Merge<P<Ts...>, P<Us...>> {
using type = P<Ts..., Us...>;
};
template <std::size_t N, typename Pack, typename Previous, typename... Output> struct PermutationNHelper;
template <std::size_t N, template <typename...> class P, typename First, typename... Rest, typename... Prev, typename... Output>
struct PermutationNHelper<N, P<First, Rest...>, P<Prev...>, Output...> : Merge<
// P<Prev..., Rest...> are the remaining elements, thus ensuring that the next
// element chosen will not be First. The new Prev... is empty since we now start
// at the first element of P<Prev..., Rest...>.
typename PermutationNHelper<N-1, P<Prev..., Rest...>, P<>, Output..., First>::type,
// Using P<Rest...> ensures that the next set of permutations will begin with the
// type after First, and thus the new Prev... is Prev..., First.
typename PermutationNHelper<N, P<Rest...>, P<Prev..., First>, Output...>::type
> {};
template <std::size_t N, template <typename...> class P, typename Previous, typename... Output>
struct PermutationNHelper<N, P<>, Previous, Output...> {
using type = P<>;
};
template <template <typename...> class P, typename First, typename... Rest, typename... Prev, typename... Output>
struct PermutationNHelper<0, P<First, Rest...>, P<Prev...>, Output...> {
using type = P<P<Output...>>;
};
template <template <typename...> class P, typename Previous, typename... Output>
struct PermutationNHelper<0, P<>, Previous, Output...> {
using type = P<P<Output...>>;
};
template <typename Pack> struct EmptyPack;
template <template <typename...> class P, typename... Ts>
struct EmptyPack<P<Ts...>> { using type = P<>; };
template <std::size_t N, typename Pack>
using PermutationN = typename PermutationNHelper<N, Pack, typename EmptyPack<Pack>::type>::type;
// Testing
template <typename...> struct P;
int main() {
std::cout << std::is_same<
PermutationN<2, P<int, char, bool>>,
P< P<int, char>, P<int, bool>, P<char, int>, P<char, bool>, P<bool, int>, P<bool, char> >
>::value << '\n'; // true
std::cout << std::is_same<
PermutationN<2, P<int, int, int>>,
P< P<int, int>, P<int, int>, P<int, int>, P<int, int>, P<int, int>, P<int, int> >
>::value << '\n'; // true (but the answer should be P< P<int, int> >.
}
注意我正在寻找一种优雅(且高效)的解决方案,它不仅仅执行上述操作,然后仅从输出中删除所有重复包(我已经可以这样做,但拒绝编写这样一个丑陋、低效的解决方案解决问题的核心),而是直接获得正确的输出。这就是我卡住的地方。
【问题讨论】:
标签: c++ templates c++11 recursion variadic-templates