Does calling a function on a temporary that returns a ref to that temporary result in accessing a dangling ref?

SOLVED

I have this code:

std::filesystem::path;
std::string filename;

// ...

if (auto full_path = (path / filename).make_preferred().u8string();
    is_media_file(full_path))
{
    // ...
}

This calls make_preferred() on the temporary (path / filename) and returns a reference to itself. I then call u8string() on it. Is that valid? Or has the temporary gone away by the time u8string() is called?

Posted Feb 19, 2022, 4:49 PM UTC

25
IyeOnline•

The result of the expression will live until the end of the statement, i.e. until the ;.

2
RealNCOP•

OK. I was worried because of code like this:

struct foo {
    // ...
    std::string str_;
    auto str() const& -> const std::string& { return str_; }
    auto str() const&& -> std::string { return str_; }
};

which has the purpose of preventing some common cases of dangling references. Since std::filesystem::path does not use this idiom it seemed like I might be running into a dangling ref case.

1
IyeOnline•

That pattern is only relevant in the case of

const auto& s = foo{}.str();

That would in fact result in s being a dangling reference unless that overload pattern was used.

In any case, the foo{} temporary will live until the end of the statement.

. Since std::filesystem::path does not use this idiom it seemed like I might be running into a dangling ref case.

It doesnt, because it doesnt need to.

If you chain make_preferred in an expression like this, it works since the object is still alive. and the .string (and friends) member functions return by value anyways, so thats not an issue either.

1
alfps•

The temporaries are destroyed at the end of the full-expression, so that part's fine.

However, u8string() result type changed in C++20.

So, unless you're doing something clever the call to is_media_file will fail either with C++17 or with C++20.

One workaround is to copy the u8string result to a std::string and use that.


I believe that the reason for the change was to sabotage Windows use of std::filesystem.

Especially Evil™ since the main reason for the existence of that functionality was the encoding problems in Windows.

Another view is that no, on the contrary, the reason was the long term goal of moving everybody over to UTF-8 encoded text handling based on char8_t type, a glorious Pascal-like C++ future.

https://en.cppreference.com/w/cpp/language/types#char8_t

0
std_bot•

Unlinked STL entries: std::filesystem std::string


^(Last update: 14.09.21. Last Change: Can now link headers like '<bitset>')Repo

2