Current status of std::make_array

As @DeiDei writes, C++17 includes template argument deduction for classes, so you can now write:

std::pair p (foo, bar);
std::array arr = { 1, 2, 3, 4, 5 };

and so on. But there are some (somewhat subtle) remaining use cases where make_pair or make_array can be useful, and you can read about them in: Usefulness of std::make_pair and std::make_tuple in C++1z


LEWG voted to forward the merge paper for C++20 back in 2016 (this was after the C++17 feature freeze). Its LWG review is on hold at the author's request pending the resolution of LWG issue 2814.


This answer provided the status of the proposal - however - it is pretty easy to implement in C++17 - at least this part:

[Example:

int i = 1; int& ri = i;
auto a1 = make_array(i, ri);         // a1 is of type array<int, 2>
auto a2 = make_array(i, ri, 42L);    // a2 is of type array<long, 3>
auto a3 = make_array<long>(i, ri);   // a3 is of type array<long, 2>
auto a4 = make_array<long>();        // a4 is of type array<long, 0>
auto a5 = make_array();              // ill-formed    auto a6 = make_array<double>(1, 2);  // ill-formed: might narrow –end example]

See:

template <typename Dest=void, typename ...Arg>
constexpr auto make_array(Arg&& ...arg) {
   if constexpr (std::is_same<void,Dest>::value)
      return std::array<std::common_type_t<std::decay_t<Arg>...>, sizeof...(Arg)>{{ std::forward<Arg>(arg)... }};
   else
      return std::array<Dest, sizeof...(Arg)>{{ std::forward<Arg>(arg)... }};
}

The proof:

int main() {
    int i = 1; int& ri = i;
    auto a1 = make_array(i, ri);         // a1 is of type array<int, 2>
    std::cout << print<decltype(a1)>().get() << std::endl; 
    auto a2 = make_array(i, ri, 42L);    // a2 is of type array<long, 3>
    std::cout << print<decltype(a2)>().get() << std::endl;
    auto a3 = make_array<long>(i, ri);   // a3 is of type array<long, 2>
    std::cout << print<decltype(a3)>().get() << std::endl;
    auto a4 = make_array<long>();        // a4 is of type array<long, 0>
    std::cout << print<decltype(a4)>().get() << std::endl;
    // auto a5 = make_array();              // ill-formed
    // auto a6 = make_array<double>(1, 2);  // ill-formed: might narrow
}

Output:

std::__1::array<int, 2ul>
std::__1::array<long, 3ul>
std::__1::array<long, 2ul>
std::__1::array<long, 0ul>

The last line make_array<double>(1, 2) produces "narrowing cast" errors - as required in proposal. It can be "improved" by adding static_cast in implementations.

On latest clang - demo.

Tags:

C++

Arrays