This is an archive of the discontinued LLVM Phabricator instance.

Add an emplace(...) method to llvm::Optional<T>.
ClosedPublic

Authored by jordan_rose on Sep 26 2014, 11:59 AM.

Details

Reviewers
dblaikie
Summary

This can be used for in-place initialization of non-moveable types. For compilers that don't support variadic templates, only up to four arguments are supported. We can always add more, of course, but this should be good enough until we move to a later MSVC that has full support for variadic templates.e

Inspired by std::experimental::optional from the "Library Fundamentals" C++ TS (API, spec).

Diff Detail

Event Timeline

jordan_rose retitled this revision from to Add an emplace(...) method 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).

I've omitted the std::experimental::optional overload that takes a std::initializer_list and additional arguments. We haven't yet found a use for it, and we can always add it later.

dblaikie added inline comments.Sep 26 2014, 12:46 PM
include/llvm/ADT/Optional.h
77

This is a tricky thing to upstream without a fallback. Do we have any other cases where we've added a variadic template without a fallback for non-variadic-template-supporting compilers? Without precedent I'd be a little hesitant to be the first example of that situation. Essentially no LLVM code would realistically use this API without a fallback, I'd imagine.

We're using it internally in our own version of Optional; my guess would be that it would only be for projects that had stricter requirements than LLVM and Clang do (like lld, which requires MSVS 2012). However, I could add the fake-variadic up-to-six-arguments fallback for now.

Oops, I meant "like lld used to". The requirements are now in sync with the rest of LLVM.

dblaikie edited edge metadata.Sep 26 2014, 3:02 PM

We're using it internally in our own version of Optional; my guess would be that it would only be for projects that had stricter requirements than LLVM and Clang do (like lld, which requires MSVS 2012). However, I could add the fake-variadic up-to-six-arguments fallback for now.

I think it's probably reasonable for you to either keep it internally (not like it'll conflict with anything) or add the fake-variadic in line with other variadics in the LLVM codebase, so we don't have code that's just have a trap for the unwary.

(we also have some variadic helper utility class too - not sure what that one was for and whether it helps here - might be worth looking at (include/llvm/ADT/VariadicFunction.h)

jordan_rose updated this object.
jordan_rose edited edge metadata.

Added non-variadic overloads for 0-4 arguments. What do you think?

dblaikie accepted this revision.Sep 30 2014, 9:27 AM
dblaikie edited edge metadata.

A few remaining questions, but I assume they're mostly in the negative (and/or the test case improvements seem obvious enough to not require another round of review)

include/llvm/ADT/Optional.h
86

I haven't looked - but I take it we have no better mechanism for stamping out these overloads more economically?

Do we have a fairly consistent habit on the number of args supported in other faux variadic situations?

unittests/ADT/OptionalTest.cpp
182

Maybe make this class non-copyable and non-movable, to ensure that emplace can be used on a non-movable type?

(or add that as a separate test - with a clear "ImmovableType" or something for testing (some of these basic feature types might eventually get pulled out into common test utility headers for use in a variety of container tests))

182

Want to try adding an explicit ctor (or making this ctor explicit) just to demonstrate that emplace can/should be able to call explicit ctors? (I assume that's the intent - I haven't checked the standard proposal, etc)

This revision is now accepted and ready to land.Sep 30 2014, 9:27 AM
jordan_rose added inline comments.Sep 30 2014, 9:34 AM
include/llvm/ADT/Optional.h
86

I checked VariadicFunction.h but that only works when the type is consistent. I could try to macro it up but it doesn't seem like that much of a win, especially when the code will probably be gone in two years.

The only other use of LLVM_HAS_VARIADIC_TEMPLATES I see is our implementation of function_ref (a class I didn't know about). That one only goes up to three arguments. I'll admit I didn't use any particular logic in picking four other than "this should hold us for a while"; the cases where we use it only go up to two.

unittests/ADT/OptionalTest.cpp
182

Good point, will do.

182

The MoveOnlyEmplace test below does test that—although it's not a non-movable type, it does track how many times the move constructor is called, and that's 0.

dblaikie added inline comments.Sep 30 2014, 9:42 AM
unittests/ADT/OptionalTest.cpp
182

Yeah - in my experience it's pretty easy to introduce a compile time dependency on the existence of certain operations even if those operations are never actually executed.

(eg: clear() could be implemented as erase(begin, end) but that requires elements to be movable to move them down to fill the space (even though, dynamically, there's nothing to move down), unique_ptr(nullptr) implemented in terms of unique_ptr() (forwarding ctor) ends up meaning that unique_ptr(nullptr) needs access to the underlying object's dtor... , etc)

jordan_rose closed this revision.Sep 30 2014, 7:23 PM

Committed in r218732, with test changes applied. I didn't end up making a general ImmovableType (ImmobileType?) because the test would have looked exactly the same.