Movatterモバイル変換


[0]ホーム

URL:



This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++23 status.

3121.tuple constructor constraints forUTypes&&... overloads

Section: 22.4.4.2[tuple.cnstr]Status:C++23Submitter: Matt CalabreseOpened: 2018-06-12Last modified: 2023-11-22

Priority:2

View otheractive issues in [tuple.cnstr].

View all otherissues in [tuple.cnstr].

View all issues withC++23 status.

Discussion:

Currently thetuple constructors of the form:

template<class... UTypes>EXPLICIT constexpr tuple(UTypes&&...);

are not properly constrained in that in the 1-elementtuple case, the constraints do no short-circuit whenthe constructor would be (incorrectly) considered as a possible copy/move constructor candidate. libc++ has aworkaround for this, but the additional short-circuiting does not actually appear in the working draft.

As an example of why this lack of short circuiting is a problem in practice, consider the following line:

bool a = std::is_copy_constructible_v<std::tuple<any>>;

The above code will cause a compile error because of a recursive trait definition. The copy constructibilitycheck implies doing substitution into theUTypes&&... constructor overloads, which in turnwill check iftuple<any> is convertible to any, which in turn will check iftuple<any>is copy constructible (and so the trait is dependent on itself).

I do not provide wording for the proposed fix in anticipation of requires clauses potentially changing how wedo the specification, however, the basic solution should be similar to what we've done for other standard librarytypes, which is to say that the very first constraint should be to check that ifsizeof...(UTypes) == 1and the type, after applyingremove_cvref_t, is thetuple type itself, then we should forcesubstitution failure rather than checking any further constraints.

[2018-06-23 after reflector discussion]

Priority set to 3

[2018-08-20, Jonathan provides wording]

[2018-08-20, Daniel comments]

The wording changes by this issue are very near to those suggested for LWG3155(i).

[2018-11 San Diego Thursday night issue processing]

Jonathan to update wording - using conjunction. Priority set to 2

Previous resolution [SUPERSEDED]:

This wording is relative toN4762.

[2021-05-20 Tim updates wording]

The new wording below also resolves LWG3155(i), relating to anallocator_arg_t tag argument being treated by this constructor templateas converting to the first tuple element instead of as a tag. To minimizecollateral damage, this wording takes this constructor out of overload resolutiononly if the tuple is of size 2 or 3, the first argument is anallocator_arg_t,but the first tuple element isn't of typeallocator_arg_t (in both casesafter removing cv/ref qualifiers). This avoids damaging tuples that actuallycontain anallocator_arg_t as the first element (which can be formedduring uses-allocator construction, thanks touses_allocator_construction_args).

The proposed wording has been implemented and tested on top of libstdc++.

[2021-08-20; LWG telecon]

Set status to Tentatively Ready after telecon review.

[2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative toN4885, and also resolves LWG3155(i).

  1. Modify 22.4.4.2[tuple.cnstr] as indicated:

    template<class... UTypes> explicit(see below) constexpr tuple(UTypes&&... u);

    -?- Letdisambiguating-constraint be:

    1. (?.1) —negation<is_same<remove_cvref_t<U0>, tuple>> ifsizeof...(Types) is 1;

    2. (?.2) — otherwise,bool_constant<!is_same_v<remove_cvref_t<U0>, allocator_arg_t> || is_same_v<remove_cvref_t<T0>, allocator_arg_t>> ifsizeof...(Types) is 2 or 3;

    3. (?.3) — otherwise,true_type.

    -12-Constraints:

    1. (12.1) —sizeof...(Types) equalssizeof...(UTypes),and

    2. (12.2) —sizeof...(Types) ≥ 1, and

    3. (12.3) —conjunction_v<disambiguating-constraint, is_constructible<Types, UTypes>...> istrueis_constructible_v<Ti, Ui>istrue for alli.

    -13-Effects: Initializes the elements in the tuple with the corresponding value instd::forward<UTypes>(u).

    -14-Remarks: The expression insideexplicit is equivalent to:

    !conjunction_v<is_convertible<UTypes, Types>...>


[8]ページ先頭

©2009-2026 Movatter.jp