Search code examples
c++variadic-templatesc++20

Shorten variadic parameter pack to N types


I would like to write a class that takes a size N (> 0) and a variable number of arguments (>= N). It should have a constructor that takes N arguments and a member std::tuple which has the same type:

template <size_t N, typename... Args>
struct Example {
  // A constructor taking N parameters of type Args[N], initializing the member tuple 
  // (e.g. param 1 has type Args[0], param 2 has type Args[1], ..., 
  // param N has type Args[N-1])
  // A tuple with N elements, each corresponding to Args[N]
  // (e.g. std::tuple<Args[0], ..., Args[N-1]>)

  //For instance Example<3, int, float, int, bool> should result in
  constexpr Example(int a, float b, int c): t(a, b, c) {}
  std::tuple<int, float, int> t;
}

In general: Is this possible? If not are there viable alternatives? Why does/ doesn't this work? I'm using C++20.


Solution

  • To the extent I understand the question, it simply seems to be asking how to produce a tuple from arguments. Which, using Boost.Mp11, is a short one-liner (as always):

    template <size_t N, typename... Args>
    using Example = mp_take_c<N, std::tuple<Args...>>;
    

    Rather than Example<3, int, float, int, bool> being some type that has a member tuple<int, float, int> with one constructor, it actually is tuple<int, float int>.

    If you, for some reason, specifically need exactly a member tuple and exactly the constructor specified, we can do easily enough:

    template <typename... Ts>
    struct ExampleImpl {
        std::tuple<Ts...> t;
        constexpr ExampleImpl(Ts... ts) : t(ts...) { }
    };
    
    template <size_t N, typename... Args>
    using Example = mp_take_c<N, ExampleImpl<Args...>>;