Home > Blockchain >  How can one construct an object from a parameter pack in a C template?
How can one construct an object from a parameter pack in a C template?

Time:12-09

Given the following, how can I correctly construct an object of an unknown type from a parameter pack?

template < typename... Types >
auto foo( Types&&... types ) {
    auto result =  Types{ }; // How should this be done?
    // Do stuff with result
    return result;
}

I expect the template function to only be called with matching types, so everything in the parameter pack should be of the same type. It doesn't matter which individual item I reference if I need to use decltype, for example (relevant code in the commented out section will cause compilation errors otherwise).

CodePudding user response:

Here is one way (assuming we are talking about relatively simple types, which can sustain copying):

template < typename... Types >
auto foo( Types&&... types ) {
    return std::array{types...}[0];
}

Here is another, more convoluted, but working way, which puts no additional limitation on types:

#include <tuple>

template < typename... Types >
auto foo( Types&&... types ) {
    using tup_t = std::tuple<Types...>;
    auto result =  std::tuple_element_t<0, tup_t>{}; 

    // Do stuff with result
    return result;
}


// auto k = foo(); // compile error

auto z = foo(10); // z is 0-initialized int

CodePudding user response:

Since all the types in the parameter pack are the same, you can first use the comma operator to expand the parameter pack, then use decltype to get the type of the last operand.

template<typename... Types>
auto foo(Types&&... types) {
  auto result = decltype((Types{}, ...)){ };
  // Do stuff with result
  return result;
}

Demo.

CodePudding user response:

Since all the types in the parameter pack are the same, you can use std::common_type_t, which gives a type that all the types in the parameter pack can be converted to.

template <typename... Types>
auto foo(Types&&... types) {
    auto result = std::common_type_t<Types...>{};
    // Do stuff with result
    return result;
}
  • Related