diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -58,6 +58,12 @@ StringView.h ) +add_header_library( + optional + HDRS + Optional.h +) + add_header_library( type_traits HDRS diff --git a/libc/src/__support/CPP/Optional.h b/libc/src/__support/CPP/Optional.h new file mode 100644 --- /dev/null +++ b/libc/src/__support/CPP/Optional.h @@ -0,0 +1,77 @@ +//===-- Standalone implementation std::optional -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H + +namespace __llvm_libc { +namespace cpp { + +// Trivial Nullopt_t struct. +struct NulloptT {}; + +// Nullopt that can be used and returned +inline constexpr NulloptT Nullopt; + +// This is very simple implementation of the std::optional class. There are a +// number of guarantees in the standard that are not made here. +// +// This class will be extended as needed in future. +template class Optional { +private: + union { + T StoredValue; + char Placeholder; + }; + bool InUse = false; + +public: + Optional() : Placeholder(0), InUse(false) {} + + Optional(const T &t) : StoredValue(t), InUse(true) {} + + Optional(NulloptT) : Placeholder(0), InUse(false) {} + + Optional(const Optional &t) : StoredValue(t.value()), InUse(true) {} + + ~Optional() { + if (InUse) + StoredValue.~T(); + } + + T value() const { return StoredValue; } + + bool has_value() const { return InUse; } + + void reset() { + if (InUse) + StoredValue.~T(); + InUse = false; + } + + constexpr explicit operator bool() const { return has_value(); } + + constexpr Optional &operator=(const T &item) { + StoredValue = item; + InUse = true; + return *this; + } + + constexpr Optional &operator=(NulloptT) { + reset(); + return *this; + } + + constexpr T &operator*() &noexcept { return StoredValue; } + + constexpr const T &operator*() const &noexcept { return StoredValue; } +}; +} // namespace cpp +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt --- a/libc/test/src/__support/CPP/CMakeLists.txt +++ b/libc/test/src/__support/CPP/CMakeLists.txt @@ -80,3 +80,14 @@ DEPENDS libc.src.__support.CPP.blockstore ) + +add_libc_unittest( + optional_test + SUITE + libc_cpp_utils_unittests + SRCS + optional_test.cpp + DEPENDS + libc.src.__support.CPP.optional + +) diff --git a/libc/test/src/__support/CPP/optional_test.cpp b/libc/test/src/__support/CPP/optional_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/__support/CPP/optional_test.cpp @@ -0,0 +1,19 @@ +//===-- Unittests for Optional --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/Optional.h" +#include "utils/UnitTest/Test.h" + +using __llvm_libc::cpp::Optional; + +TEST(LlvmLibcOptionalTest, Tests) { + Optional ABC(12); + ASSERT_TRUE(ABC.has_value()); + ASSERT_EQ(ABC.value(), 12); + ASSERT_EQ(*ABC, 12); +} diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -75,6 +75,12 @@ deps = [":libc_root", "__support_cpp_uint"], ) +cc_library( + name = "__support_cpp_optional", + hdrs = ["src/__support/CPP/Optional.h"], + deps = [":libc_root"], +) + cc_library( name = "__support_cpp_string_view", hdrs = ["src/__support/CPP/StringView.h"],