C++的14版可以看看如下:
#include <tuple>
#include <utility>
#include <iostream>
#include <initializer_list>
template <class Foo, class Tuple, size_t... Is, size_t... Is2>
int all_combinations_impl(Foo foo, Tuple t, std::index_sequence<Is...> , std::integral_constant<size_t, 0>, std::index_sequence<Is2...>) {
foo(std::get<Is>(t)...);
std::cout << std::endl;
return 0;
}
template <class Foo, class Tuple, size_t... Is, size_t K, size_t... Is2>
int all_combinations_impl(Foo foo, Tuple t, std::index_sequence<Is...>, std::integral_constant<size_t, K>, std::index_sequence<Is2...> is) {
std::initializer_list<int> all = {all_combinations_impl(foo, t, std::index_sequence<Is..., Is2>{}, std::integral_constant<size_t, K-1>{}, is)...};
(void)all;
}
template <size_t K, class Foo, class Tuple>
void all_combinations(Foo foo, Tuple t) {
all_combinations_impl(foo, t, std::index_sequence<>{}, std::integral_constant<size_t, K>{}, std::make_index_sequence<std::tuple_size<Tuple>::value>{});
}
int main() {
all_combinations<2>([](auto... args) { std::forward_as_tuple((std::cout << args)...); }, std::make_tuple("1 ", "2 ", "3 "));
}
不幸的是C++ 11没有附带std::integer_sequence
,所以我们需要做额外的实施:
#include <tuple>
#include <utility>
#include <iostream>
#include <initializer_list>
template <class T, T... Vs>
struct integer_sequence { };
template <class T, class, class, class = integer_sequence<T>, class = integer_sequence<T, 0>, class = void>
struct make_integer_sequence_impl;
template <class T, T ICV1, T... Res, T... Pow>
struct make_integer_sequence_impl<T, std::integral_constant<T, ICV1>, std::integral_constant<T, 0>, integer_sequence<T, Res...>, integer_sequence<T, Pow...>, typename std::enable_if<(ICV1 > 0)>::type>: make_integer_sequence_impl<T, std::integral_constant<T, ICV1/2>, std::integral_constant<T, ICV1%2>, integer_sequence<T, Res...>, integer_sequence<T, Pow..., (Pow + sizeof...(Pow))...>> { };
template <class T, T ICV1, T... Res, T... Pow>
struct make_integer_sequence_impl<T, std::integral_constant<T, ICV1>, std::integral_constant<T, 1>, integer_sequence<T, Res...>, integer_sequence<T, Pow...>, void>: make_integer_sequence_impl<T, std::integral_constant<T, ICV1/2>, std::integral_constant<T, ICV1%2>, integer_sequence<T, Pow..., (Res + sizeof...(Pow))...>, integer_sequence<T, Pow..., (Pow + sizeof...(Pow))...>> { };
template <class T, class Res, class Pow>
struct make_integer_sequence_impl<T, std::integral_constant<T, 0>, std::integral_constant<T, 0>, Res, Pow, void> {
using type = Res;
};
template <class T, T V>
using make_integer_sequence = typename make_integer_sequence_impl<T, std::integral_constant<T, V/2>, std::integral_constant<T, V%2>>::type;
template <size_t V>
using make_index_sequence = make_integer_sequence<size_t, V>;
template <size_t... V>
using index_sequence = integer_sequence<size_t, V...>;
template <class Foo, class Tuple, size_t... Is, size_t... Is2>
int all_combinations_impl(Foo foo, Tuple t, index_sequence<Is...> , std::integral_constant<size_t, 0>, index_sequence<Is2...>) {
foo(std::get<Is>(t)...);
std::cout << std::endl;
return 0;
}
template <class Foo, class Tuple, size_t... Is, size_t K, size_t... Is2>
int all_combinations_impl(Foo foo, Tuple t, index_sequence<Is...>, std::integral_constant<size_t, K>, index_sequence<Is2...> is) {
std::initializer_list<int> all = {all_combinations_impl(foo, t, index_sequence<Is..., Is2>{}, std::integral_constant<size_t, K-1>{}, is)...};
(void)all;
}
template <size_t K, class Foo, class Tuple>
void all_combinations(Foo foo, Tuple t) {
all_combinations_impl(foo, t, index_sequence<>{}, std::integral_constant<size_t, K>{}, make_index_sequence<std::tuple_size<Tuple>::value>{});
}
struct s {
template <class... Args>
void operator()(Args... args) const {
std::forward_as_tuple((std::cout << args)...);
}
};
int main() {
all_combinations<3>(s{}, std::make_tuple("1 ", "2 ", "3 "));
}
你只想要模板编程的答案?如果没有,我认为std :: next_permutation {1,1,2,2}可能会有所帮助。 –
@KenmanTsang我没有想过运行时的方法,但它看起来很有前途...... –
@ W.K。是的,编译时间的方法是最好的!但运行时方法可能是您的最终解决方案出来之前的解决方案 –