From: Tudor Bosman Date: Sat, 16 Aug 2014 22:09:20 +0000 (-0700) Subject: Add Optional::value_or X-Git-Tag: v0.22.0~394 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=65902504332d7f856a1fa407b0930ab5cc55fb2a;p=folly.git Add Optional::value_or Summary: Common pattern: a function returns Optional, indicating whether some X was present or not; you want a default value if the X was not present. Requires that X is copiable. Test Plan: optional_test (test added) Reviewed By: tjackson@fb.com Subscribers: aalexandre, fjargsto, jhj, ntv, lesha, kma FB internal diff: D1502397 --- diff --git a/folly/Optional.h b/folly/Optional.h index eb8de160..eea1957c 100644 --- a/folly/Optional.h +++ b/folly/Optional.h @@ -225,6 +225,17 @@ class Optional { const Value* operator->() const { return &value(); } Value* operator->() { return &value(); } + // Return a copy of the value if set, or a given default if not. + template + Value value_or(U&& dflt) const& { + return hasValue_ ? value_ : std::forward(dflt); + } + + template + Value value_or(U&& dflt) && { + return hasValue_ ? std::move(value_) : std::forward(dflt); + } + private: template void construct(Args&&... args) { diff --git a/folly/test/OptionalTest.cpp b/folly/test/OptionalTest.cpp index 79968d01..efea777f 100644 --- a/folly/test/OptionalTest.cpp +++ b/folly/test/OptionalTest.cpp @@ -97,15 +97,49 @@ TEST(Optional, Const) { TEST(Optional, Simple) { Optional opt; EXPECT_FALSE(bool(opt)); + EXPECT_EQ(42, opt.value_or(42)); opt = 4; EXPECT_TRUE(bool(opt)); EXPECT_EQ(4, *opt); + EXPECT_EQ(4, opt.value_or(42)); opt = 5; EXPECT_EQ(5, *opt); opt.clear(); EXPECT_FALSE(bool(opt)); } +TEST(Optional, value_or_rvalue_arg) { + Optional opt; + std::string dflt = "hello"; + EXPECT_EQ("hello", opt.value_or(dflt)); + EXPECT_EQ("hello", dflt); + EXPECT_EQ("hello", opt.value_or(std::move(dflt))); + EXPECT_EQ("", dflt); + EXPECT_EQ("world", opt.value_or("world")); + + dflt = "hello"; + // Make sure that the const overload works on const objects + const auto& optc = opt; + EXPECT_EQ("hello", optc.value_or(dflt)); + EXPECT_EQ("hello", dflt); + EXPECT_EQ("hello", optc.value_or(std::move(dflt))); + EXPECT_EQ("", dflt); + EXPECT_EQ("world", optc.value_or("world")); + + dflt = "hello"; + opt = "meow"; + EXPECT_EQ("meow", opt.value_or(dflt)); + EXPECT_EQ("hello", dflt); + EXPECT_EQ("meow", opt.value_or(std::move(dflt))); + EXPECT_EQ("hello", dflt); // only moved if used +} + +TEST(Optional, value_or_noncopyable) { + Optional> opt; + std::unique_ptr dflt(new int(42)); + EXPECT_EQ(42, *std::move(opt).value_or(std::move(dflt))); +} + TEST(Optional, EmptyConstruct) { Optional opt; EXPECT_FALSE(bool(opt));