This is an archive of the discontinued LLVM Phabricator instance.

Add a forwarding variadic constructor to llvm::Optional<T>.
AbandonedPublic

Authored by jordan_rose on Sep 26 2014, 3:20 PM.

Details

Reviewers
dblaikie
Summary

This makes it easier to return values convertible to T when the return type is Optional<T>. This is not a feature in the C++ Library Fundamentals TS for std::experimental::optional, but we've found it useful internally.

This is more controversial than the last three diffs I've posted, because it does make things potentially more ambiguous. In particular, David remarked:

A direct variadic ctor for Optional<T> that builds a T seems a bit subtle/surprising/easily ambiguous - a utility make function is probably more appropriate (make_optional to go with make_unique, etc?).

We've been using this internally already, and the most motivating case was trying to return a type constructed from multiple arguments, i.e.

Optional<std::pair<int, int>> test() {
  return { 1, 2 };
}

There's also an annoyance with implicit conversions needing to be made explicit:

Optional<StringRef> x = ""; // rejected

Optional<StringRef> test() {
  return ""; // rejected
}

But I do know that Implicit Conversions Are Dangerous, and I'd be willing to withdraw this (and go change our internal code), particularly if someone comes up with an example of this going awry.

(I've marked David as a reviewer because he took an interest in my original post, but I'd welcome comments from anyone here.)

Diff Detail

Event Timeline

jordan_rose retitled this revision from to Add a forwarding variadic constructor to llvm::Optional<T>..
jordan_rose updated this object.
jordan_rose edited the test plan for this revision. (Show Details)
jordan_rose added a reviewer: dblaikie.
jordan_rose added a subscriber: Unknown Object (MLST).
dblaikie edited edge metadata.Sep 29 2014, 3:15 PM

Any idea if this has been discussed in the C++ standards committee proposal? (be good to know if it was considered & rejected, and if so why)

one thing that might be confusing would be:

Optional<T> func() {
  return {};
}

Does your implementation have trouble with copying a volatile Optional<T>, perhaps? (you've accounted for const/non-const, but not necessarily volatile/non-volatile) I suspect, if we're going for this, the right thing to do is to SFINAE the whole varargs ctor to ensure it's only available when the T is constructible (and, to be precise, /implicitly/ constructible) from the args. This way it won't accidentally steal away Optional(Optional) constructions, etc.

But as with another patch - I'd be concerned that this is just an in-tree trap, since the implementation isn't portable to MSVC, so no in-tree code could realistically use this.

jordan_rose abandoned this revision.Sep 29 2014, 3:51 PM

Another interesting case that came up was passing an value of type Foo * to a parameter of type Optional<FooWrapper>.

I did forget to include the implicitly-constructible-only constraint, but I think I'm going to just abandon this; we weren't using it quite as frequently as I remembered, and it's not something the standard will ever do.