Produce std::tuple of same type in compile time given its length by a template argument

前端 未结 5 1881
礼貌的吻别
礼貌的吻别 2021-02-13 10:18

In c++, how can I implement a function with an int template argument indicating the tuple length and produce a std::tuple with that length?

E.g.

func<         


        
相关标签:
5条回答
  • 2021-02-13 10:34

    Using an index_sequence and a helper type alias you can generate the type you want:

    // Just something to take a size_t and give the type `int`
    template <std::size_t>
    using Integer = int;
    
    // will get a sequence of Is = 0, 1, ..., N
    template <std::size_t... Is>
    auto func_impl(std::index_sequence<Is...>) {
        // Integer<Is>... becomes one `int` for each element in Is...
        return std::tuple<Integer<Is>...>{};
    }
    
    template <std::size_t N>
    auto func() {
        return func_impl(std::make_index_sequence<N>{});
    }
    

    It is worth calling out that in the general case you would probably be better with a std::array, (in your case you can't use one), but a std::array can behave like a tuple, similarly to a std::pair.

    Update: since you've made it clear you're working with c++11 and not 14+, you'll need to get an implementation of index_sequence and related from somewhere (here is libc++'s). Here is the C++11 version of func and func_impl with explicit return types:

    template <std::size_t... Is>
    auto func_impl(std::index_sequence<Is...>) -> std::tuple<Integer<Is>...> {
      return std::tuple<Integer<Is>...>{};
    }
    
    template <std::size_t N>
    auto func() -> decltype(func_impl(std::make_index_sequence<N>{})) {
      return func_impl(std::make_index_sequence<N>{});
    }
    
    0 讨论(0)
  • 2021-02-13 10:40

    Here are two boost.hana solutions (C++14):

    //first
    hana::replicate<hana::tuple_tag>(int{}, hana::size_c<2>);
    
    //second
    hana::cycle(std::make_tuple(int{}), hana::size_c<2>);
    

    Both produce integer-tuples of size 2, but instead of std::tuples they yield hana::tuples.

    0 讨论(0)
  • 2021-02-13 10:43

    The plain old recursion is your friend:

    template<std::size_t N>
    auto array_tuple() {
        return std::tuple_cat(std::tuple<int>{}, array_tuple<N-1>());
    }
    
    template<>
    auto array_tuple<0>() {
        return std::tuple<>{};
    }
    
    0 讨论(0)
  • 2021-02-13 10:44

    If you're okay with a C++14 solution, Ryan's answer is the way to go.

    With C++11, you can do the following (still based on index_sequence, but that's implementable in C++11):

    template <size_t N, class T, class = std::make_index_sequence<N>>
    struct n_tuple;
    
    template <size_t N, class T, size_t... Is>
    struct n_tuple<N, T, std::index_sequence<Is...>> {
        template <size_t >
        using ignore = T;
    
        using type = std::tuple<ignore<Is>...>;
    };
    
    template <size_t N, class T>
    using n_tuple_t = typename n_tuple<N, T>::type;
    

    With that:

    template <size_t N>
    n_tuple_t<N, int> func() {
        return n_tuple_t<N, int>{};
    }
    
    0 讨论(0)
  • 2021-02-13 10:47

    Here is a recursive solution with alias template and it's implementable in C++11:

    template <size_t I,typename T> 
    struct tuple_n{
        template< typename...Args> using type = typename tuple_n<I-1, T>::template type<T, Args...>;
    };
    
    template <typename T> 
    struct tuple_n<0, T> {
        template<typename...Args> using type = std::tuple<Args...>;   
    };
    template <size_t I,typename T>  using tuple_of = typename tuple_n<I,T>::template type<>;
    

    For example if we want "tuple of 3 doubles" we can write:

    tuple_of<3, double> t;
    
    0 讨论(0)
提交回复
热议问题