]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add util::value_or_throw function
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 14 Jul 2021 08:07:15 +0000 (10:07 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 19 Jul 2021 06:43:52 +0000 (08:43 +0200)
src/util/expected_utils.hpp [new file with mode: 0644]
unittest/CMakeLists.txt
unittest/test_util_expected_utils.cpp [new file with mode: 0644]

diff --git a/src/util/expected_utils.hpp b/src/util/expected_utils.hpp
new file mode 100644 (file)
index 0000000..0297a9a
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2021 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include <utility>
+
+namespace util {
+
+// --- Interface ---
+
+// Return value of `value` (where `T` typically is `nonstd::expected`) or throw
+// an exception of type `E` with a `T::error_type` as the argument.
+template<typename E, typename T>
+typename T::value_type value_or_throw(const T& value);
+template<typename E, typename T>
+typename T::value_type value_or_throw(T&& value);
+
+// --- Inline implementations ---
+
+template<typename E, typename T>
+inline typename T::value_type
+value_or_throw(const T& value)
+{
+  if (value) {
+    return *value;
+  } else {
+    throw E(value.error());
+  }
+}
+
+template<typename E, typename T>
+inline typename T::value_type
+value_or_throw(T&& value)
+{
+  if (value) {
+    return std::move(*value);
+  } else {
+    throw E(value.error());
+  }
+}
+
+} // namespace util
index 2d5b2d87049fa2224891bfaf5c9ad7685a97ee69..a9ef05e51565c4bf9a04189baab4fc77a2e409e1 100644 (file)
@@ -22,8 +22,9 @@ set(
   test_compopt.cpp
   test_hashutil.cpp
   test_util_Tokenizer.cpp
-  test_util_string_utils.cpp
+  test_util_expected_utils.cpp
   test_util_path_utils.cpp
+  test_util_string_utils.cpp
 )
 
 if(INODE_CACHE_SUPPORTED)
diff --git a/unittest/test_util_expected_utils.cpp b/unittest/test_util_expected_utils.cpp
new file mode 100644 (file)
index 0000000..316ea4b
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2021 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include <util/expected_utils.hpp>
+
+#include <third_party/doctest.h>
+#include <third_party/nonstd/expected.hpp>
+
+#include <iostream> // macOS bug: https://github.com/onqtam/doctest/issues/126
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+class TestException : public std::runtime_error
+{
+  using std::runtime_error::runtime_error;
+};
+
+TEST_CASE("util::value_or_throw")
+{
+  using util::value_or_throw;
+
+  SUBCASE("const ref")
+  {
+    const nonstd::expected<int, const char*> with_value = 42;
+    const nonstd::expected<int, const char*> without_value =
+      nonstd::make_unexpected("no value");
+
+    CHECK(value_or_throw<TestException>(with_value) == 42);
+    CHECK_THROWS_WITH(value_or_throw<TestException>(without_value), "no value");
+  }
+
+  SUBCASE("move")
+  {
+    const std::string value = "value";
+    nonstd::expected<std::unique_ptr<std::string>, const char*> with_value =
+      std::make_unique<std::string>(value);
+    CHECK(*value_or_throw<TestException>(std::move(with_value)) == value);
+  }
+}