Jiří Lechner
Jiří Lechner

Reputation: 820

How to efficiently return an std::optional

I would like to ask how to return an std::optional in an efficient way and I would like to use std::make_optional(). For example lets have this code snippet:

std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
  std::error_code errorCode;
  const auto result = std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode);
  return !errorCode ? std::make_optional(result) : std::nullopt;
}

I am particularly interested whether there is any optimization in passing result to std::make_optional. Would it be better to use std::make_optional(std::move(result))?

And does it prevent any RVO or NVRO? The result is a local variable but it is not exactly in a return statement so I assume the compiler can't use move by itself.

Upvotes: 14

Views: 9311

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118310

There's one obvious improvement:

std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
  std::error_code errorCode;
  auto result = std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode);
  return !errorCode ? std::make_optional(std::move(result)) : std::nullopt;
}

Making the transitory object const will require employing copy-construction as part of instantiating the returned std::optional. This tweak should result in employing move semantics.

After this point, any further improvements would dependent highly on the compiler behavior. It's unlikely, but it's possible that, if benchmarked, some minor performance variances can be observed with alternate syntaxes, such as, for example:

std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
  std::error_code errorCode;
  auto result = std::make_optional(std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode));

  if (errorCode)
     result.reset();

  return result;
}

If it's determined that the compiler will choose to elide the copy, as allowed by NVRO, then it's worth benchmarking this, as well. But only actual benchmarking will produce useful results.

Upvotes: 16

Related Questions