Is it possible to invoke a method with all possible K-combinations (with repetition) of arguments passed in a tuple?

后端 未结 1 997
南旧
南旧 2021-01-20 17:12

The desired behaviour can be illustrated as follows:

void foo(int x, int y) {
    std::cout << x << \" \" << y << std::endl;
}

int m         


        
相关标签:
1条回答
  • 2021-01-20 17:55

    The c++14 version could look as follows:

    #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 "));
    }
    

    Unfortunately c++11 does not come with std::integer_sequence, so we need to do additional implementation:

    #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 "));
    }
    
    0 讨论(0)
提交回复
热议问题