From f96d35d143e95925e33ce7383658d6907098d59e Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Wed, 14 Jul 2021 10:07:15 +0200 Subject: [PATCH] Add util::value_or_throw function --- src/util/expected_utils.hpp | 58 +++++++++++++++++++++++++++ unittest/CMakeLists.txt | 3 +- unittest/test_util_expected_utils.cpp | 55 +++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/util/expected_utils.hpp create mode 100644 unittest/test_util_expected_utils.cpp diff --git a/src/util/expected_utils.hpp b/src/util/expected_utils.hpp new file mode 100644 index 000000000..0297a9a96 --- /dev/null +++ b/src/util/expected_utils.hpp @@ -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 + +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 T::value_type value_or_throw(const T& value); +template +typename T::value_type value_or_throw(T&& value); + +// --- Inline implementations --- + +template +inline typename T::value_type +value_or_throw(const T& value) +{ + if (value) { + return *value; + } else { + throw E(value.error()); + } +} + +template +inline typename T::value_type +value_or_throw(T&& value) +{ + if (value) { + return std::move(*value); + } else { + throw E(value.error()); + } +} + +} // namespace util diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 2d5b2d870..a9ef05e51 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -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 index 000000000..316ea4bf2 --- /dev/null +++ b/unittest/test_util_expected_utils.cpp @@ -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 + +#include +#include + +#include // macOS bug: https://github.com/onqtam/doctest/issues/126 +#include +#include +#include + +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 with_value = 42; + const nonstd::expected without_value = + nonstd::make_unexpected("no value"); + + CHECK(value_or_throw(with_value) == 42); + CHECK_THROWS_WITH(value_or_throw(without_value), "no value"); + } + + SUBCASE("move") + { + const std::string value = "value"; + nonstd::expected, const char*> with_value = + std::make_unique(value); + CHECK(*value_or_throw(std::move(with_value)) == value); + } +} -- 2.47.3