Skip to content

<scoped_allocator>, <xpolymorphic_allocator.h>: Pre-C++20 overload set of construct might be incorrect #3383

@frederick-vs-ja

Description

@frederick-vs-ja

Describe the bug
This program is well-formed in C++17 (but ill-formed since C++20 due to WG21-P0591), because the overload set of construct was specially designed for std::pair (N4659 [mem.poly.allocator.mem], cppreference).

#include <cstddef>
#include <memory_resource>
#include <type_traits>
#include <utility>

int main()
{
    std::pair<int, int> pr{};
    std::pmr::polymorphic_allocator<std::byte> pa{};

    pa.construct<int, int>(&pr);
}

However, MSVC STL always implements the C++20 overload set of construct, and hence rejects this program in C++17 mode (Godbolt link).

template <class _Uty, class... _Types>
void construct(_Uty* const _Ptr, _Types&&... _Args) {
// propagate allocator *this if uses_allocator_v<_Uty, polymorphic_allocator>
#if _HAS_CXX20
_STD uninitialized_construct_using_allocator(_Ptr, *this, _STD forward<_Types>(_Args)...);
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
allocator<char> _Al{};
_Uses_allocator_construct(_Ptr, _Al, *this, _STD forward<_Types>(_Args)...);
#endif // ^^^ !_HAS_CXX20 ^^^
}

scoped_allocator_adaptor::construct has exactly the same issue.

template <class _Ty, class... _Types>
void construct(_Ty* _Ptr, _Types&&... _Args) { // construct with varying allocator styles
#if _HAS_CXX20
_STD apply(
[_Ptr, this](auto&&... _New_args) {
_Scoped_outermost_traits<scoped_allocator_adaptor>::construct(
_Scoped_outermost(*this), _Ptr, _STD forward<decltype(_New_args)>(_New_args)...);
},
_STD uses_allocator_construction_args<_Ty>(inner_allocator(), _STD forward<_Types>(_Args)...));
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Uses_allocator_construct(_Ptr, _Scoped_outermost(*this), inner_allocator(), _STD forward<_Types>(_Args)...);
#endif // ^^^ !_HAS_CXX20 ^^^
}

The issue has been present even before implementing WG21-P0591 (#1668). I'm not sure whether this is a bug or an intentional design.

Additional context
LWG-3677 may be related to this if we want consistent behaviors in C++17 & C++20 modes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions