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++17 status.

2586. Wrong value category used inscoped_allocator_adaptor::construct()

Section: 20.6.4[allocator.adaptor.members], 20.2.8.2[allocator.uses.construction]Status:C++17Submitter: Jonathan WakelyOpened: 2016-01-15Last modified: 2017-07-30

Priority:0

View all otherissues in [allocator.adaptor.members].

View all issues withC++17 status.

Discussion:

20.6.4[allocator.adaptor.members] p9 says that theis_constructibletests are done usinginner_allocator_type, which checks forconstruction from an rvalue, but then the constructor is passedinner_allocator() which returns a non-const lvalue reference. Thevalue categories should be consistent, otherwise this fails tocompile:

#include <memory>#include <scoped_allocator>struct X {  using allocator_type = std::allocator<X>;  X(std::allocator_arg_t, allocator_type&&) { }  X(allocator_type&) { }};int main() {  std::scoped_allocator_adaptor<std::allocator<X>> sa;  sa.construct(sa.allocate(1));}

uses_allocator<X, decltype(sa)::inner_allocator_type>> is true, becauseit can be constructed from an rvalue of the allocator type, so bullet (9.1) doesn't apply.

is_constructible<X, allocator_arg_t, decltype(sa)::inner_allocator_type> is true, so bullet (9.2) applies.That means we try to construct the object passing itsa.inner_allocator() which is an lvalue reference, so it fails.

Theis_constructible checks should use an lvalue reference, as that'swhat's actually going to be used.

I don't think the same problem exists in the related wording in20.2.8.2[allocator.uses.construction] if we assume that the value categoriesofv1, v2, ..., vN andalloc are meant to be preserved, so that theis_constructible traits and the initialization expressions match.However, it does say "an allocatoralloc of typeAlloc" and ifAllocis an reference type then it's not an allocator, so I suggest a small tweak there too.

[2016-02, Issues Telecon]

Strike first paragraph of PR, and move to Tentatively Ready.

Original Resolution [SUPERSEDED]:
  1. Change 20.2.8.2[allocator.uses.construction] p1:

    -1- Uses-allocator construction with allocatorAlloc refers to the construction of an objectobj of typeT, using constructor argumentsv1, v2, ..., vN of typesV1, V2, ..., VN, respectively, and an allocator(or reference to an allocator)alloc of typeAlloc, according to the following rules:

  2. Change the 2nd and 3rd bullets in 20.6.4[allocator.adaptor.members] p9 to add two lvalue-references:

    1. (9.2) — Otherwise, ifuses_allocator<T, inner_allocator_type>::value istrue andis_constructible<T, allocator_arg_t, inner_allocator_type&, Args...>::value istrue, callsOUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg, inner_allocator(), std::forward<Args>(args)...).

    2. (9.3) — Otherwise, ifuses_allocator<T, inner_allocator_type>::value istrue andis_constructible<T, Args..., inner_allocator_type&>::value istrue, callsOUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, std::forward<Args>(args)...,inner_allocator()).

  3. Change the 2nd, 3rd, 6th, and 7th bullets in 20.6.4[allocator.adaptor.members] p11 toadd four lvalue-references:

    1. (11.2) — Otherwise, ifuses_allocator<T1, inner_allocator_type>::value istrue andis_constructible<T1, allocator_arg_t, inner_allocator_type&, Args1...>::value istrue, thenxprime istuple_cat(tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()), std::move(x)).

    2. (11.3) — Otherwise, ifuses_allocator<T1, inner_allocator_type>::value istrue andis_constructible<T1, Args1..., inner_allocator_type&>::value istrue, thenxprime istuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator())).

    3. […]

    4. (11.6) — Otherwise, ifuses_allocator<T2, inner_allocator_type>::value istrue andis_constructible<T2, allocator_arg_t, inner_allocator_type&, Args2...>::value istrue, thenyprime istuple_cat(tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()), std::move(y)).

    5. (11.7) — Otherwise, ifuses_allocator<T2, inner_allocator_type>::value istrue andis_constructible<T2, Args2..., inner_allocator_type&>::value istrue, thenyprime istuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator())).

[2016-02, Issues Telecon]

P0; move to Tentatively Ready.

Proposed resolution:

This wording is relative to N4567.

  1. Change the 2nd and 3rd bullets in 20.6.4[allocator.adaptor.members] p9 to add two lvalue-references:

    1. (9.2) — Otherwise, ifuses_allocator<T, inner_allocator_type>::value istrue andis_constructible<T, allocator_arg_t, inner_allocator_type&, Args...>::value istrue, callsOUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg, inner_allocator(), std::forward<Args>(args)...).

    2. (9.3) — Otherwise, ifuses_allocator<T, inner_allocator_type>::value istrue andis_constructible<T, Args..., inner_allocator_type&>::value istrue, callsOUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, std::forward<Args>(args)...,inner_allocator()).

  2. Change the 2nd, 3rd, 6th, and 7th bullets in 20.6.4[allocator.adaptor.members] p11 toadd four lvalue-references:

    1. (11.2) — Otherwise, ifuses_allocator<T1, inner_allocator_type>::value istrue andis_constructible<T1, allocator_arg_t, inner_allocator_type&, Args1...>::value istrue, thenxprime istuple_cat(tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()), std::move(x)).

    2. (11.3) — Otherwise, ifuses_allocator<T1, inner_allocator_type>::value istrue andis_constructible<T1, Args1..., inner_allocator_type&>::value istrue, thenxprime istuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator())).

    3. […]

    4. (11.6) — Otherwise, ifuses_allocator<T2, inner_allocator_type>::value istrue andis_constructible<T2, allocator_arg_t, inner_allocator_type&, Args2...>::value istrue, thenyprime istuple_cat(tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()), std::move(y)).

    5. (11.7) — Otherwise, ifuses_allocator<T2, inner_allocator_type>::value istrue andis_constructible<T2, Args2..., inner_allocator_type&>::value istrue, thenyprime istuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator())).


[8]ページ先頭

©2009-2026 Movatter.jp