C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Stop gap required for NRVO until Anton's paper is assimilated

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Fri, 19 Jul 2024 10:59:23 +0100
On Thu, Jul 18, 2024 at 11:58 PM Tiago Freire wrote:
>
> I have just seen you change the design 3 times with
> the drop of a hat every time some one mentions a
> new type of code flow. And there's no guarantee that
> tomorrow you won't change it again once you remember
> something else.


I'm blushing Tiago, you flatter me. I have been known to quickly
improvise and come out with innovative designs at the drop of a hat,
thank you. My favourite flower is still the tulip and I'm unwilling to
compromise on beauty -- perhaps it really is in the eye of the
beholder but I adamantly assert that there is innate beauty in the
tulip.

Let's do another complex NRVO function. Let's say we have a function
with the following signature:

    std::fstream GetLicenseFile(void);

This function will go through all the files in the current directory,
opening them one by one and looking for one that starts with the
3-byte sequence "LIS", and returning the 'fstream' for that file. If
no such file can be found, a new file is created called
"new_license_file.txt".

The "std::fstream" class is actually movable but let's pretend it's
both unmovable-and-uncopyable. If we had NRVO in C++, it would look
something like:

    std::fstream GetLicenseFile(void)
    {
        typedef std::filesystem::directory_iterator DirIt;
        DirIt it{ std::filesystem::current_path() };

        for ( DirIt it(std::filesystem::current_path()); DirIt() != it; ++it )
        {
            std::fstream a( it->path().string() );
            if ( a.is_open() )
            {
                char buf[3u] = {};
                a.read(buf,3u);
                if ( 3u==a.gcount() && 'L'==buf[0] && 'I'==buf[1] &&
'S'==buf[2] ) return a;
            }
        }

        return std::fstream("new_license_file.txt");
    }

With P3357, this function would be written as:

    std::fstream GetLicenseFile(void)
    {
        using std::fstream;

        constexpr auto something_went_wrong =
            +[](void) -> fstream
            {
            return fstream("new_license_file.txt");
            };

        typedef std::filesystem::directory_iterator DirIt;
        DirIt it{ std::filesystem::current_path() };
        if ( DirIt() == it ) return something_went_wrong();
        std::string name = it->path().string();

        return std::construct_modify_retry<fstream>(
            name, // passed by reference
            [&](auto &a) -> Status
            {
                if ( a.is_open() )
                {
                    char buf[3u] = {};
                    a.read(buf,3u);
                    if ( 3u==a.gcount() && 'L'==buf[0] && 'I'==buf[1]
&& 'S'==buf[2] ) return Success;
                }
                if ( DirIt() == ++it ) return Fail;
                name = it->path().string();
                return Retry;
            },
            something_went_wrong
        );
    }

which is tested and working on this GodBolt:

      https://msvc.godbolt.org/z/6jdWaMWjo

Received on 2024-07-19 09:59:36