You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
5.2 KiB

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <vector>
#include <string>
#include <optional>
namespace folly {
template <class Value>
class Optional;
struct None {
enum class _secret { _token };
explicit constexpr None(_secret) {}
};
constexpr None none{None::_secret::_token};
template <class Value>
class Optional {
public:
typedef Value value_type;
constexpr Optional();
Optional(const Optional& src);
constexpr Optional(const None&) noexcept;
constexpr Optional(const Value& newValue);
void assign(const None&);
void assign(const Optional& src);
Optional& operator=(None) noexcept {
reset();
return *this;
}
Optional& operator=(const Optional& other) {
assign(other);
return *this;
}
template <class... Args>
Value& emplace(Args&&... args);
void reset() noexcept;
constexpr Value& value() &;
constexpr const Value& value() const&;
constexpr bool has_value() const noexcept;
constexpr explicit operator bool() const noexcept { return has_value(); }
constexpr const Value* operator->() const { return &value(); }
constexpr Value* operator->() { return &value(); }
template <class U>
constexpr Value value_or(U&& dflt) const&;
};
} // namespace folly
int not_none_ok() {
folly::Optional<int> foo{5};
return foo.value();
}
// missing a more precise model for
// constructing an optional from a value
int not_none_check_value_ok_FP() {
folly::Optional<int> foo{5};
int x = foo.value();
if (x != 5) {
folly::Optional<int> foo{folly::none};
return foo.value();
}
return x;
}
int none_check_ok() {
folly::Optional<int> foo{folly::none};
if (foo) {
return foo.value();
}
return -1;
}
int none_no_check_bad() {
folly::Optional<int> foo{folly::none};
return foo.value();
}
int none_copy_ok() {
folly::Optional<int> foo{5};
folly::Optional<int> bar{foo};
return bar.value();
}
int none_copy_bad() {
folly::Optional<int> foo{folly::none};
folly::Optional<int> bar{foo};
return bar.value();
}
int assign_ok() {
folly::Optional<int> foo{5};
folly::Optional<int> bar{foo};
foo = folly::none;
return bar.value();
}
int assign_bad() {
folly::Optional<int> foo{folly::none};
folly::Optional<int> bar{5};
int sum = bar.value();
bar = foo;
sum += bar.value();
return sum;
}
int assign2_bad() {
folly::Optional<int> foo{5};
int sum = foo.value();
foo = folly::none;
sum += foo.value();
return sum;
}
struct State {
std::vector<int> vec;
};
void emplace(folly::Optional<State> state) {
if (state) {
state.emplace();
}
auto pos = state->vec.begin();
}
void operator_arrow_bad() { emplace(folly::none); }
int value_or_check_empty_ok() {
folly::Optional<int> foo{folly::none};
if (foo.value_or(0) > 0) {
return foo.value();
}
return -1;
}
// missing a more precise model for
// constructing an optional from a value
int value_or_check_value_ok_FP() {
folly::Optional<int> foo{5};
int x = foo.value_or(0);
if (x != 5) {
folly::Optional<int> foo{folly::none};
return foo.value();
}
return -1;
}
int test_trace_ref() {
folly::Optional<int> foo{5};
int sum = foo.value();
foo = folly::none;
int& x = foo.value();
sum += x;
return sum;
}
struct StringWrapper {
static folly::Optional<StringWrapper> get_optional() {
return StringWrapper();
};
std::string x;
};
std::string get_optional_string_wrapper_ok() {
return StringWrapper::get_optional().value().x.data();
}
int std_not_none_ok() {
std::optional<int> foo{5};
return foo.value();
}
int std_not_none_check_value_ok_FP() {
std::optional<int> foo{5};
int x = foo.value();
if (x != 5) {
std::optional<int> foo{std::nullopt};
return foo.value();
}
return x;
}
int std_none_check_ok() {
std::optional<int> foo{std::nullopt};
if (foo) {
return foo.value();
}
return -1;
}
int std_none_no_check_bad() {
std::optional<int> foo{std::nullopt};
return foo.value();
}
int std_none_copy_ok() {
std::optional<int> foo{5};
std::optional<int> bar{foo};
return bar.value();
}
int std_none_copy_bad() {
std::optional<int> foo{std::nullopt};
std::optional<int> bar{foo};
return bar.value();
}
int std_assign_ok() {
std::optional<int> foo{5};
std::optional<int> bar{foo};
foo = std::nullopt;
return bar.value();
}
int std_assign_bad() {
std::optional<int> foo{std::nullopt};
std::optional<int> bar{5};
int sum = bar.value();
bar = foo;
sum += bar.value();
return sum;
}
int std_assign2_bad() {
std::optional<int> foo{5};
int sum = foo.value();
foo = std::nullopt;
sum += foo.value();
return sum;
}
void std_emplace(std::optional<State> state) {
if (state) {
state.emplace();
}
auto pos = state->vec.begin();
}
void std_operator_arrow_bad() { std_emplace(std::nullopt); }
int std_value_or_check_empty_ok() {
std::optional<int> foo{std::nullopt};
if (foo.value_or(0) > 0) {
return foo.value();
}
return -1;
}
int std_value_or_check_value_ok_FP() {
std::optional<int> foo{5};
int x = foo.value_or(0);
if (x != 5) {
std::optional<int> foo{std::nullopt};
return foo.value();
}
return -1;
}