On 11/2/25 04:09, Jonathan Wakely wrote:


On Sat, 1 Nov 2025, 21:10 François Dumont, <[email protected]> wrote:

    Hi

    Here is the implementation of the std::__debug::inplace_vector.


It looks like this is going to repeat the assertions in e.g. operator[], front, back etc because those already have assertions in the base class.

This is I think unavoidable if you want to cover direct usages of __gnu_debug::inplace_vector like in 23_containers/inplace_vector/debug/invalidation/*.cc tests.



    I eventually had to introduce a dedicated std::erase_if/std::erase
    implementation for the __debug version. When directly using
    __gnu_debug::inplace_vector the std::erase_if was used downcasting the


If it's converting to a base, it's upcasting.


    inplace_vector into the std::inplace_vector base class so breaking
    encapsulation. So we really need dedicated implementations and I'll
    prepare patches for other containers.


Why is the implicit cast a problem? We know that erase_if doesn't iterate past the end, and only dereferences valid iterators. That's one of the benefits of using erase_if: it ensures the container is accessed safely.
The problem is that the std::__debug::inplace_vector is not aware of the invalidated iterators.

Is encapsulation broken if a standard library function does that implicit cast? Is it observable to users?
Yes, some iterators might not be invalidated as they should.



    I also added tests for std::swap. Overloading it in std:: namespace
    seems the best option to me. If it is defined in std::__debug:: as it
    should then calls to std::swap in user code are replaced by the
    generic
call to swap in move.h instead of calling inplace_vector<>::swap.

Users should call swap not std::swap. That was the consensus when LWG discussed https://cplusplus.github.io/LWG/issue4250

Ok, I'll remove the test case with the call to std::swap then.



    It
    still works to invalidate iterators but is a major performance
    issue. I
    noticed this running in gdb, is there a way to test for call to the
    correct swap ?

    I also wonder in
    testsuite/23_containers/inplace_vector/debug/invalidation/swap.cc
    test02
    how gcc does to find the proper swap method on the unqualified call ?


Argument Dependent Lookup ?

That's what it should be but container is in std::__debug:: whereas the swap definition is in std::.

I'll have some more tests but with your remark above I think I'll just defined swap as friend in std::__debug::inplace_vector like it's done in std::inplace_vector.




         Add _GLIBCXX_DEBUG std::inplace_vector implementation.

         Unlike other _GLIBCXX_DEBUG containers the
    std::__debug::inplace_vector is
         inheriting privately from both __gnu_debug::_Safe_sequence<> and
    std::inplace_vector
         classes to preserve encapsulation. Iterators won't be created or
    invalidated without
    std::__debug::inplace_vector being aware. However
    std::__debug::inplace_vector<T, 0>
         inherits publicly from std::inplace_vector<T, 0> to benefit from
    the same std::
         functions overloads.

         libstdc++-v3/ChangeLog:

                 * include/Makefile.am (debug_headers): Add
    inplace_vector.
                 * include/Makefile.in: Regenerate.
                 * include/debug/inplace_vector: New.
                 * include/debug/safe_base.h (~_Safe_sequence_base()):
    Add
    C++11 noexcept
                 qualification.
                 (_Safe_sequence_base::operator=(const
    _Safe_sequence_base&)): New.
    (_Safe_sequence_base::operator=(_Safe_sequence_base&&)): New.
                 (_Safe_sequence_base::_M_invalidate_all): Add C++20
    constexpr qualification.
                 * include/debug/safe_container.h
                 (_Safe_container::operator=(const _Safe_container&)):
    Implement using same
                 _Safe_sequence_base operator.
                 * include/std/inplace_vector
    [_GLIBCXX_DEBUG](std::inplace_vector<>): Move
                 implementation into __cxx1998 namespace.
                 (erase, erase_if): Limit to non-debug inplace_vector<>,
    cleanup code.
                 [_GLIBCXX_DEBUG]: Add include <debug/inplace_vector>.
                 * testsuite/23_containers/inplace_vector/cons/1.cc:
    Adapt,
    skip several
                 is_trivially_xxx checks when in _GLIBCXX_DEBUG mode.
                 * testsuite/23_containers/inplace_vector/copy.cc:
    Likewise.
                 * testsuite/23_containers/inplace_vector/move.cc:
    Likewise.
                 *
    testsuite/23_containers/inplace_vector/debug/assign1_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/assign2_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/assign3_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/assign4_backtrace_neg.cc:

    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/assign4_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/construct1_neg.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/construct2_neg.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/construct3_neg.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/construct4_neg.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/debug_functions.cc: New
    test case.
                 * testsuite/23_containers/inplace_vector/debug/erase.cc:
    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/insert1_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/insert2_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/insert3_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/insert4_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/insert5_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/insert7_neg.cc: New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/1.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/2.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/3.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/4.cc:
    New test
    case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/append_range.cc:

    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/erase.cc:
    New
    test case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/pop_back.cc:

    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/push_back.cc:

    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/swap.cc:
    New
    test case.
                 *
    
testsuite/23_containers/inplace_vector/debug/invalidation/try_append_range.cc:

    New test case.
                 *
    
testsuite/23_containers/inplace_vector/debug/invalidation/try_emplace_back.cc:

    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/invalidation/try_push_back.cc:

    New test case.
                 *
    
testsuite/23_containers/inplace_vector/debug/invalidation/unchecked_emplace_back.cc:

    New test case.
                 *
    testsuite/23_containers/inplace_vector/debug/multithreaded_swap.cc:
    New
    test case.
                 * testsuite/util/debug/checks.h: Avoid using
    _GLIBCXX_DEBUG
    containers in test
                 implementations.

    Tested under Linux x86_64.

    Ok to commit ?

    PR: https://forge.sourceware.org/gcc/gcc-TEST/pulls/119

    François

Reply via email to