Doc. no.: | N3824 |
---|---|
Date: | 2013-10-22 |
Project: | Programming Language C++, Library Evolution Working Group |
Reply-to: | Zhihao Yuan <zy at miator dot net> |
We have make_tuple
, make_pair
, but not make_array
, while std::array
creation can also benefit from this “semiofficial” tuple-like interface to deduce both element type and array bound.
LWG 851 intended to provide a replacement syntax to
array<T, N> a = { E1, E2, ... };
, so the following
auto a = make_array(42u, 3.14);
is well-formed (with additional static_cast
s applied inside) because
array<double, 2> = { 42u, 3.14 };
is well-formed.
This paper intends to provide a set of std::array
creation interfaces which are comprehensive from both tuple
’s point of view and array
’s point of view, so narrowing is just naturally banned. See more details driven by this direction in Design Decisions.
auto a1 = make_array(2, 3L); // array<long, 2>
auto ax = make_array(2, 3U); // error: narrowing
auto a2 = make_array<long>(2, 3U); // explicit destination type
auto ax = make_array<unsigned>(2, 3U); // error: narrowing
auto a3 = make_array("foo"); // array<char const*, 1>, decayed
auto a4 = to_array("foo"); // array<char, 4>
Provide both make_tuple
-like, type-deduced interface and raw array style bound-deduced interface.
Ban reference_wrapper
in the make_tuple
-like interface. make_tuple
and make_pair
have special handling of reference_wrapper
, then user might expect that the expression
also results in a tuple-like object storing
T&
. However,std::array
does not store “real” references, and any attempts to workaround this break the interfaces in different ways.
make_tuple
and make_pair
unconditionally decay, but such a behavior, when being applied to make_array
,is inexplicable. However, to keep the interfaces consistent, I decide to name a new utility differently instead of to ban this conversion.
This wording is relative to N3797, which contains the resolution of LWG 2141.
Add to 23.3.1/2 [sequences.general], <array>
synopsis:
namespace std {
template <class T, size_t N > struct array;
…
template <class T, size_t N >
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y)));
…
}
New section 23.3.2.9 [array.creation] (between [array.zero] and [array.tuple], which was 23.3.2.9):
23.3.2.9 Array creation functions [array.creation]
template <class... Types>
constexpr array<CT, sizeof...(Types)> make_array(Types&&...);
Let
Ui
beremove_reference<
Ti
>::type
for eachTi
inTypes
.
Remarks: This function shall not participate in overload resolution unless each
Ui
is notreference_wrapper<
Ti
>
.
[Just a note: This one is banned for genericity reason, so use SFINAE to allow users to handle them in generic code. –end note]
Returns: An
array<CT, sizeof...(Types)>
initialized with{ std::forward<Types>(t))... }
, whereCT
iscommon_type<Types...>::type
.
[Example:
int i = 1; int& ri = i;
make_array(i, ri, 42L)
creates an
array
of type
array<long, 3>
–end example]
template <class D, class... Types>
constexpr array<D, sizeof...(Types)> make_array(Types&&...);
Returns: An
array<D, sizeof...(Types)>
initialized with{ std::forward<Types>(t))... }
.
template <class T, size_t N>
constexpr array<V, N> to_array(T (&a)[N]);
Returns: An
array<V, N>
such that each element is copy-initialized with the corresponding element ofa
, whereV
isremove_cv<T>::type
.
[Just a note: The remove_cv
here functionally performs decay, while intentionally kills constructing from multidimensional array with a hard error, because std::array
is not aware of multidimensional array (yet), and I don’t want user to try anything may silently break their code in the future. On the other hand, if you understand multidimensional std::array
as array
of array
s, it might be more convenient and clear to write
make_array(make_array(1, 2, 3), make_array(4, 5, 6)...)
instead of to adapt a raw array. –end note]
A sample implementation is available at https://gist.github.com/lichray/6034753.
Jonathan Wakely, who showed me how index_sequence
helps initializing std::array
from a raw array.
Daniel Krügler, who explained why an explicit destination type is essential.
Ville Voutilainen and other people who reviewed this paper.