Title
simplified array construction
Status
nad
Section
[array]
Submitter
Benjamin Kosnik

Created on 2008-06-05.00:00:00 last changed 91 months ago

Messages

Date: 2017-06-06.14:03:11

Proposed resolution:

  1. Add to the array synopsis in [sequences]:

    template<class... Args>
      array<CT, sizeof...(Args)>
      make_array(Args&&... args);
    
  2. Append after [array.tuple] "Tuple interface to class template array" the following new section:

    XX.X.X.X Array creation functions [array.creation]

    
    template<class... Args>
    array<CT, sizeof...(Args)>
    make_array(Args&&... args)
    

    Let CT be decay<common_type<Args...>::type>::type.

    Returns: An array<CT, sizeof...(Args)> initialized with { static_cast<CT>(std::forward<Args>(args))... }.

    [Example:

    
    int i = 0; int& ri = i;
    make_array(42u, i, 2.78, ri);
    

    returns an array of type

    
    array<double, 4>
    

    end example]

Date: 2017-06-02.00:00:00

[ 2017-06-02 Issues Telecon ]

It seems as if deduction guides can solve most of the problem. In addition to that, make_array is available in Library Fundamentals TS v2. If it's desired to be able to specify the type but not the extent, make_array can do that, and if make_array isn't acceptable for that, we are talking about a language extension in deduction guides, which needs a proposal paper.

Resolve as NAD

Date: 2017-06-06.14:03:11

[ 2017-02 in Kona, LEWG recommends NAD ]

Date: 2015-11-15.00:00:00

[ 2015-11-29, Alisdair comments ]

N4391 was adopted for Fundamentals 2 at the Lenexa meeting.

Date: 2010-10-21.18:28:33

[ 2009-10 Santa Cruz: ]

Argument for NAD future: everything about this could be added on. This does not require changes to the existing text.

Date: 2009-07-25.00:00:00

[ 2009-07-25 Daniel provides rewritten proposed resolution. ]

Date: 2010-10-21.18:28:33

[ 2009-07 Frankfurt: ]

The proposed resolution uses concepts.

Daniel to rewrite the proposed resolution.

Leave Open.

Date: 2009-06-07.00:00:00

[ 2009-06-07 Daniel adds: ]

I suggest a fix and a simplification of the current proposal: Recent prototyping by Howard showed, that a fix is required because narrowing conversion [dcl.init.list]/6 b.3 would severely limit the possible distribution of argument types, e.g. the expression make_array<double>(1, 2.0) is ill-formed, because the narrowing happens inside the function body where no constant expressions exist anymore. Furthermore given e.g.

int f();
double g();

we probably want to support

make_array<double>(f(), g());

as well. To make this feasible, the currently suggested expansion

{ std::forward<Args>(args)... }

needs to be replaced by

{ static_cast<T>(std::forward<Args>(args))... }

which is safe, because we already ensure convertibility via the element-wise Convertible<Args, T> requirement. Some other fixes are necessary: The ValueType requirement for the function parameters is invalid, because all lvalue arguments will deduce to an lvalue-reference, thereby no longer satisfying this requirement.

The suggested simplification is to provide a default-computed effective type for the result array based on common_type and decay, in unconstrained form:

template<typename... Args>
array<typename decay<typename common_type<Args...>::type>::type,
sizeof...(Args)>
make_array(Args&&... args);

The approach used below is similar to that of make_pair and make_tuple using a symbol C to represent the decayed common type [Note: Special handling of reference_wrapper types is intentionally not provided, because our target has so satisfy ValueType, thus under the revised proposal only an all-reference_wrapper-arguments would be well-formed and an array of reference_wrapper will be constructed]. I do currently not suggest to add new concepts reflecting decay and common_type, but an implementor will need something like this to succeed. Note that we use a similar fuzziness for make_pair and make_tuple currently. This fuzziness is not related to the currently missing Constructible<Vi, Ti&&> requirement for those functions. The following proposal fixes that miss for make_array. If the corresponding C type deduction is explicitly wanted for standardization, here the implementation

auto concept DC<typename... T> {
  typename type = typename decay<typename common_type<T...>::type>::type;
}

where C is identical to DC<Args...>::type in the proposed resolution below.

I intentionally added no further type relation between type and the concept template parameters, but instead added this requirement below to make the specification as transparent as possible. As written this concept is satisfied, if the corresponding associated type exists.

Suggested Resolution:

  1. Add to the array synopsis in [sequences]:

    
    template<ReferentType... Args>
    requires ValueType<C> && IdentityOf<Args> && Constructible<C, Args&&>...
    array<C, sizeof...(Args)>
    make_array(Args&&... args);
    
    
  2. Append after [array.tuple] Tuple interface to class template array the following new section:

    23.4.1.7 Array creation functions [array.creation]

    
    template<ReferentType... Args>
    requires ValueType<C> && IdentityOf<Args> && Constructible<C, Args&&>...
    array<C, sizeof...(Args)>
    make_array(Args&&... args);
    

    Let C be decay<common_type<Args...>::type>::type.

    Returns: an array<C, sizeof...(Args)> initialized with { static_cast<C>(std::forward<Args>(args))... }.

Date: 2010-10-21.18:28:33

[ San Francisco: ]

Benjamin: Move to Ready?

Bjarne: I'm not convinced this is useful enough to add, so I'd like us to have time to reflect on it.

Alisdair: the constraints are wrong, they should be

template<ValueType T, ValueType... Args>
requires Convertible<Args, T>...
array<T, sizeof...(Args)> make_array(Args&&... args);

Alidair: this would be useful if we had a constexpr version.

Bjarne: this is probably useful for arrays with a small number of elements, but it's not clearly useful otherwise.

Consensus is to move to Open.

Date: 2008-06-05.00:00:00

This is an issue that came up on the libstdc++ list, where a discrepancy between "C" arrays and C++0x's std::array was pointed out.

In "C," this array usage is possible:

int ar[] = {1, 4, 6};

But for C++,

std::array<int> a = { 1, 4, 6 }; // error

Instead, the second parameter of the array template must be explicit, like so:

std::array<int, 3> a = { 1, 4, 6 };

Doug Gregor proposes the following solution, that assumes generalized initializer lists.

template<typename T, typename... Args>
inline array<T, sizeof...(Args)> 
make_array(Args&&... args) 
{ return { std::forward<Args>(args)... };  }

Then, the way to build an array from a list of unknown size is:

auto a = make_array<T>(1, 4, 6);
History
Date User Action Args
2017-06-06 14:03:11adminsetmessages: + msg9234
2017-06-06 14:03:11adminsetmessages: + msg9233
2017-06-06 14:03:11adminsetstatus: lewg -> nad
2015-12-14 22:26:48adminsetmessages: + msg7645
2014-11-24 15:11:58adminsetstatus: nad future -> lewg
2010-10-21 18:28:33adminsetmessages: + msg4050
2010-10-21 18:28:33adminsetmessages: + msg4049
2010-10-21 18:28:33adminsetmessages: + msg4048
2010-10-21 18:28:33adminsetmessages: + msg4047
2010-10-21 18:28:33adminsetmessages: + msg4046
2010-10-21 18:28:33adminsetmessages: + msg4045
2008-06-05 00:00:00admincreate