Search code examples
c++pointersc++23

Understanding std::inout_ptr and std::out_ptr in C++23


I've being reading the list of library changes proposed for C++23 and I'm quite curious about the std::out_ptr and std::inout_ptr (their _t siblings). As far as I understand they are some kind of wrapper for smart pointers to be compatible with raw pointers, but I haven't managed to understand them yet. Maybe someone here is familiar with the proposal or may give a less ISO-like explanation or examples?


Solution

  • TL;DR - it is for simpler and more seemless interoperability between C out/inout pointer parameters and smart pointers

    Longer answer

    Let's separate the stuff. std::out_ptr and std::inout_ptr are functions used to create objects of type std::out_ptr_t and std::inout_ptr_t respectively. What are those types and functions for? Let's look at an example inspired by this (for simplicity I replaced generic argument with good ol' int):

    int foreign_resetter(int**);
    auto up = std::make_unique<int>(5);
     
    if (int ec = foreign_resetter(std::inout_ptr(up)) {
        return ec;
    }
    

    As you see std::inout_ptr_t created with std::inout_ptr is passed to function taking pointer to pointer to the template argument of std::unique_ptr. Before adding std::inout_ptr_t interoperation with old C in-out pointer parameters was much more cumbersome and error prone. It would look more less like this:

    int foreign_resetter(int**);
    auto up = std::make_unique<int>(5);
     
    int* up_raw = up.release();
    if (int ec = foreign_resetter(&up_raw)) {
        return ec;
    }
    up.reset(up_raw);
    

    Differences out_ptr vs inout_ptr

    From the proposal P1132:

    inout_ptr's semantics are exactly like out_ptr's, just with the additional requirement that it calls .release() on the smart pointer upon constructing the temporary inout_ptr_t.

    This is because the foreign_resetter might delete a pointer before setting a new one, calling .release() reserves that behavior and can be safer. Use inout_ptr if your pointer is already valid and allocated, and out_ptr if the smart pointer is empty.