diff --git a/misc/style/run-clang-tidy.py b/misc/style/run-clang-tidy.py index 9218e65289..90ad7a31d4 100755 --- a/misc/style/run-clang-tidy.py +++ b/misc/style/run-clang-tidy.py @@ -29,7 +29,7 @@ def check_search_code_with_clang_tidy(): src_files = utils.get_src_files(search_dir, (".h", ".cc")) compile_commands = [{ "directory": os.path.join(build_dir, "search"), - "command": "g++ -I{}/ext -std=c++11 -c {}".format(search_dir, src_file), + "command": "g++ -std=c++20 -c {}".format(src_file), "file": src_file} for src_file in src_files ] @@ -82,8 +82,6 @@ def check_search_code_with_clang_tidy(): "-quiet", "-p", build_dir, "-clang-tidy-binary=clang-tidy-12", - # Include all non-system headers (.*) except the ones from search/ext/. - "-header-filter=.*,-tree.hh,-tree_util.hh", "-checks=-*," + ",".join(checks)] print("Running clang-tidy: " + " ".join(pipes.quote(x) for x in cmd)) print() diff --git a/src/search/CMakeLists.txt b/src/search/CMakeLists.txt index 7de536ebf9..79579c2480 100644 --- a/src/search/CMakeLists.txt +++ b/src/search/CMakeLists.txt @@ -29,10 +29,6 @@ fast_downward_set_linker_flags() include("${CMAKE_CURRENT_SOURCE_DIR}/DownwardFiles.cmake") add_executable(downward ${PLANNER_SOURCES}) -## == Includes == - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/ext) - ## == Libraries == # On Linux, find the rt library for clock_gettime(). diff --git a/src/search/ext/optional.hh b/src/search/ext/optional.hh deleted file mode 100644 index 15302fb444..0000000000 --- a/src/search/ext/optional.hh +++ /dev/null @@ -1,2359 +0,0 @@ -// -// optional - An implementation of std::optional with extensions -// Written in 2017 by Simon Brand (tartanllama@gmail.com, @TartanLlama) -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. If not, see -// . -/// - -#ifndef TL_OPTIONAL_HPP -#define TL_OPTIONAL_HPP - -#define TL_OPTIONAL_VERSION_MAJOR 0 -#define TL_OPTIONAL_VERSION_MINOR 5 - -#include -#include -#include -#include -#include - -#if (defined(_MSC_VER) && _MSC_VER == 1900) -#define TL_OPTIONAL_MSVC2015 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ - !defined(__clang__)) -#define TL_OPTIONAL_GCC49 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ - !defined(__clang__)) -#define TL_OPTIONAL_GCC54 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ - !defined(__clang__)) -#define TL_OPTIONAL_GCC55 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ - !defined(__clang__)) -// GCC < 5 doesn't support overloading on const&& for member functions -#define TL_OPTIONAL_NO_CONSTRR - -// GCC < 5 doesn't support some standard C++11 type traits -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ - std::has_trivial_copy_constructor::value -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign::value - -// This one will be different for GCC 5.7 if it's ever supported -#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value - -// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector -// for non-copyable types -#elif (defined(__GNUC__) && __GNUC__ < 8 && \ - !defined(__clang__)) -#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -namespace tl { - namespace detail { - template - struct is_trivially_copy_constructible : std::is_trivially_copy_constructible{}; -#ifdef _GLIBCXX_VECTOR - template - struct is_trivially_copy_constructible> - : std::is_trivially_copy_constructible{}; -#endif - } -} -#endif - -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ - tl::detail::is_trivially_copy_constructible::value -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ - std::is_trivially_copy_assignable::value -#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value -#else -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ - std::is_trivially_copy_constructible::value -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ - std::is_trivially_copy_assignable::value -#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value -#endif - -#if __cplusplus > 201103L -#define TL_OPTIONAL_CXX14 -#endif - -// constexpr implies const in C++11, not C++14 -#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \ - defined(TL_OPTIONAL_GCC49)) -/// \exclude -#define TL_OPTIONAL_11_CONSTEXPR -#else -/// \exclude -#define TL_OPTIONAL_11_CONSTEXPR constexpr -#endif - -namespace tl { -#ifndef TL_MONOSTATE_INPLACE_MUTEX -#define TL_MONOSTATE_INPLACE_MUTEX -/// \brief Used to represent an optional with no data; essentially a bool -class monostate {}; - -/// \brief A tag type to tell optional to construct its value in-place -struct in_place_t { - explicit in_place_t() = default; -}; -/// \brief A tag to tell optional to construct its value in-place -static constexpr in_place_t in_place{}; -#endif - -template class optional; - -/// \exclude -namespace detail { -#ifndef TL_TRAITS_MUTEX -#define TL_TRAITS_MUTEX -// C++14-style aliases for brevity -template using remove_const_t = typename std::remove_const::type; -template -using remove_reference_t = typename std::remove_reference::type; -template using decay_t = typename std::decay::type; -template -using enable_if_t = typename std::enable_if::type; -template -using conditional_t = typename std::conditional::type; - -// std::conjunction from C++17 -template struct conjunction : std::true_type {}; -template struct conjunction : B {}; -template -struct conjunction - : std::conditional, B>::type {}; - -#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L -#define TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND -#endif - -// In C++11 mode, there's an issue in libc++'s std::mem_fn -// which results in a hard-error when using it in a noexcept expression -// in some cases. This is a check to workaround the common failing case. -#ifdef TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND -template struct is_pointer_to_non_const_member_func : std::false_type{}; -template -struct is_pointer_to_non_const_member_func : std::true_type{}; -template -struct is_pointer_to_non_const_member_func : std::true_type{}; -template -struct is_pointer_to_non_const_member_func : std::true_type{}; -template -struct is_pointer_to_non_const_member_func : std::true_type{}; -template -struct is_pointer_to_non_const_member_func : std::true_type{}; -template -struct is_pointer_to_non_const_member_func : std::true_type{}; - -template struct is_const_or_const_ref : std::false_type{}; -template struct is_const_or_const_ref : std::true_type{}; -template struct is_const_or_const_ref : std::true_type{}; -#endif - -// std::invoke from C++17 -// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround -template ::value - && is_const_or_const_ref::value)>, -#endif - typename = enable_if_t>::value>, - int = 0> -constexpr auto invoke(Fn &&f, Args &&... args) noexcept( - noexcept(std::mem_fn(f)(std::forward(args)...))) - -> decltype(std::mem_fn(f)(std::forward(args)...)) { - return std::mem_fn(f)(std::forward(args)...); -} - -template >::value>> -constexpr auto invoke(Fn &&f, Args &&... args) noexcept( - noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) { - return std::forward(f)(std::forward(args)...); -} - -// std::invoke_result from C++17 -template struct invoke_result_impl; - -template -struct invoke_result_impl< - F, decltype(detail::invoke(std::declval(), std::declval()...), void()), - Us...> { - using type = decltype(detail::invoke(std::declval(), std::declval()...)); -}; - -template -using invoke_result = invoke_result_impl; - -template -using invoke_result_t = typename invoke_result::type; -#endif - -// std::void_t from C++17 -template struct voider { using type = void; }; -template using void_t = typename voider::type; - -// Trait for checking if a type is a tl::optional -template struct is_optional_impl : std::false_type {}; -template struct is_optional_impl> : std::true_type {}; -template using is_optional = is_optional_impl>; - -// Change void to tl::monostate -template -using fixup_void = conditional_t::value, monostate, U>; - -template > -using get_map_return = optional>>; - -// Check if invoking F for some Us returns void -template struct returns_void_impl; -template -struct returns_void_impl>, U...> - : std::is_void> {}; -template -using returns_void = returns_void_impl; - -template -using enable_if_ret_void = enable_if_t::value>; - -template -using disable_if_ret_void = enable_if_t::value>; - -template -using enable_forward_value = - detail::enable_if_t::value && - !std::is_same, in_place_t>::value && - !std::is_same, detail::decay_t>::value>; - -template -using enable_from_other = detail::enable_if_t< - std::is_constructible::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value>; - -template -using enable_assign_forward = detail::enable_if_t< - !std::is_same, detail::decay_t>::value && - !detail::conjunction, - std::is_same>>::value && - std::is_constructible::value && std::is_assignable::value>; - -template -using enable_assign_from_other = detail::enable_if_t< - std::is_constructible::value && - std::is_assignable::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value && - !std::is_assignable &>::value && - !std::is_assignable &&>::value && - !std::is_assignable &>::value && - !std::is_assignable &&>::value>; - -#ifdef _MSC_VER -// TODO make a version which works with MSVC -template struct is_swappable : std::true_type {}; - -template struct is_nothrow_swappable : std::true_type {}; -#else -// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept -namespace swap_adl_tests { -// if swap ADL finds this then it would call std::swap otherwise (same -// signature) -struct tag {}; - -template tag swap(T &, T &); -template tag swap(T (&a)[N], T (&b)[N]); - -// helper functions to test if an unqualified swap is possible, and if it -// becomes std::swap -template std::false_type can_swap(...) noexcept(false); -template (), std::declval()))> -std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), - std::declval()))); - -template std::false_type uses_std(...); -template -std::is_same(), std::declval())), tag> -uses_std(int); - -template -struct is_std_swap_noexcept - : std::integral_constant::value && - std::is_nothrow_move_assignable::value> {}; - -template -struct is_std_swap_noexcept : is_std_swap_noexcept {}; - -template -struct is_adl_swap_noexcept - : std::integral_constant(0))> {}; -} // namespace swap_adl_tests - -template -struct is_swappable - : std::integral_constant< - bool, - decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype(detail::swap_adl_tests::uses_std(0))::value || - (std::is_move_assignable::value && - std::is_move_constructible::value))> {}; - -template -struct is_swappable - : std::integral_constant< - bool, - decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype( - detail::swap_adl_tests::uses_std(0))::value || - is_swappable::value)> {}; - -template -struct is_nothrow_swappable - : std::integral_constant< - bool, - is_swappable::value && - ((decltype(detail::swap_adl_tests::uses_std(0))::value - &&detail::swap_adl_tests::is_std_swap_noexcept::value) || - (!decltype(detail::swap_adl_tests::uses_std(0))::value && - detail::swap_adl_tests::is_adl_swap_noexcept::value))> { -}; -#endif - -// The storage base manages the actual storage, and correctly propagates -// trivial destruction from T. This case is for when T is not trivially -// destructible. -template ::value> -struct optional_storage_base { - TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept - : m_dummy(), m_has_value(false) {} - - template - TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u) - : m_value(std::forward(u)...), m_has_value(true) {} - - ~optional_storage_base() { - if (m_has_value) { - m_value.~T(); - m_has_value = false; - } - } - - struct dummy {}; - union { - dummy m_dummy; - T m_value; - }; - - bool m_has_value; -}; - -// This case is for when T is trivially destructible. -template struct optional_storage_base { - TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept - : m_dummy(), m_has_value(false) {} - - template - TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u) - : m_value(std::forward(u)...), m_has_value(true) {} - - // No destructor, so this class is trivially destructible - - struct dummy {}; - union { - dummy m_dummy; - T m_value; - }; - - bool m_has_value = false; -}; - -// This base class provides some handy member functions which can be used in -// further derived classes -template struct optional_operations_base : optional_storage_base { - using optional_storage_base::optional_storage_base; - - void hard_reset() noexcept { - get().~T(); - this->m_has_value = false; - } - - template void construct(Args &&... args) noexcept { - new (std::addressof(this->m_value)) T(std::forward(args)...); - this->m_has_value = true; - } - - template void assign(Opt &&rhs) { - if (this->has_value()) { - if (rhs.has_value()) { - this->m_value = std::forward(rhs).get(); - } else { - this->m_value.~T(); - this->m_has_value = false; - } - } - - else if (rhs.has_value()) { - construct(std::forward(rhs).get()); - } - } - - bool has_value() const { return this->m_has_value; } - - TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; } - TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; } - TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); } -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr const T &&get() const && { return std::move(this->m_value); } -#endif -}; - -// This class manages conditionally having a trivial copy constructor -// This specialization is for when T is trivially copy constructible -template -struct optional_copy_base : optional_operations_base { - using optional_operations_base::optional_operations_base; -}; - -// This specialization is for when T is not trivially copy constructible -template -struct optional_copy_base : optional_operations_base { - using optional_operations_base::optional_operations_base; - - optional_copy_base() = default; - optional_copy_base(const optional_copy_base &rhs) { - if (rhs.has_value()) { - this->construct(rhs.get()); - } else { - this->m_has_value = false; - } - } - - optional_copy_base(optional_copy_base &&rhs) = default; - optional_copy_base &operator=(const optional_copy_base &rhs) = default; - optional_copy_base &operator=(optional_copy_base &&rhs) = default; -}; - -// This class manages conditionally having a trivial move constructor -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_constructible. We -// have to make do with a non-trivial move constructor even if T is trivially -// move constructible -#ifndef TL_OPTIONAL_GCC49 -template ::value> -struct optional_move_base : optional_copy_base { - using optional_copy_base::optional_copy_base; -}; -#else -template struct optional_move_base; -#endif -template struct optional_move_base : optional_copy_base { - using optional_copy_base::optional_copy_base; - - optional_move_base() = default; - optional_move_base(const optional_move_base &rhs) = default; - - optional_move_base(optional_move_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value) { - if (rhs.has_value()) { - this->construct(std::move(rhs.get())); - } else { - this->m_has_value = false; - } - } - optional_move_base &operator=(const optional_move_base &rhs) = default; - optional_move_base &operator=(optional_move_base &&rhs) = default; -}; - -// This class manages conditionally having a trivial copy assignment operator -template -struct optional_copy_assign_base : optional_move_base { - using optional_move_base::optional_move_base; -}; - -template -struct optional_copy_assign_base : optional_move_base { - using optional_move_base::optional_move_base; - - optional_copy_assign_base() = default; - optional_copy_assign_base(const optional_copy_assign_base &rhs) = default; - - optional_copy_assign_base(optional_copy_assign_base &&rhs) = default; - optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) { - this->assign(rhs); - return *this; - } - optional_copy_assign_base & - operator=(optional_copy_assign_base &&rhs) = default; -}; - -// This class manages conditionally having a trivial move assignment operator -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_assignable. We have -// to make do with a non-trivial move assignment operator even if T is trivially -// move assignable -#ifndef TL_OPTIONAL_GCC49 -template ::value - &&std::is_trivially_move_constructible::value - &&std::is_trivially_move_assignable::value> -struct optional_move_assign_base : optional_copy_assign_base { - using optional_copy_assign_base::optional_copy_assign_base; -}; -#else -template struct optional_move_assign_base; -#endif - -template -struct optional_move_assign_base : optional_copy_assign_base { - using optional_copy_assign_base::optional_copy_assign_base; - - optional_move_assign_base() = default; - optional_move_assign_base(const optional_move_assign_base &rhs) = default; - - optional_move_assign_base(optional_move_assign_base &&rhs) = default; - - optional_move_assign_base & - operator=(const optional_move_assign_base &rhs) = default; - - optional_move_assign_base & - operator=(optional_move_assign_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_assignable::value) { - this->assign(std::move(rhs)); - return *this; - } -}; - -// optional_delete_ctor_base will conditionally delete copy and move -// constructors depending on whether T is copy/move constructible -template ::value, - bool EnableMove = std::is_move_constructible::value> -struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base &) = default; - optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default; - optional_delete_ctor_base & - operator=(const optional_delete_ctor_base &) = default; - optional_delete_ctor_base & - operator=(optional_delete_ctor_base &&) noexcept = default; -}; - -template struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base &) = default; - optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete; - optional_delete_ctor_base & - operator=(const optional_delete_ctor_base &) = default; - optional_delete_ctor_base & - operator=(optional_delete_ctor_base &&) noexcept = default; -}; - -template struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base &) = delete; - optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default; - optional_delete_ctor_base & - operator=(const optional_delete_ctor_base &) = default; - optional_delete_ctor_base & - operator=(optional_delete_ctor_base &&) noexcept = default; -}; - -template struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base &) = delete; - optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete; - optional_delete_ctor_base & - operator=(const optional_delete_ctor_base &) = default; - optional_delete_ctor_base & - operator=(optional_delete_ctor_base &&) noexcept = default; -}; - -// optional_delete_assign_base will conditionally delete copy and move -// constructors depending on whether T is copy/move constructible + assignable -template ::value && - std::is_copy_assignable::value), - bool EnableMove = (std::is_move_constructible::value && - std::is_move_assignable::value)> -struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base &) = default; - optional_delete_assign_base(optional_delete_assign_base &&) noexcept = - default; - optional_delete_assign_base & - operator=(const optional_delete_assign_base &) = default; - optional_delete_assign_base & - operator=(optional_delete_assign_base &&) noexcept = default; -}; - -template struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base &) = default; - optional_delete_assign_base(optional_delete_assign_base &&) noexcept = - default; - optional_delete_assign_base & - operator=(const optional_delete_assign_base &) = default; - optional_delete_assign_base & - operator=(optional_delete_assign_base &&) noexcept = delete; -}; - -template struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base &) = default; - optional_delete_assign_base(optional_delete_assign_base &&) noexcept = - default; - optional_delete_assign_base & - operator=(const optional_delete_assign_base &) = delete; - optional_delete_assign_base & - operator=(optional_delete_assign_base &&) noexcept = default; -}; - -template struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base &) = default; - optional_delete_assign_base(optional_delete_assign_base &&) noexcept = - default; - optional_delete_assign_base & - operator=(const optional_delete_assign_base &) = delete; - optional_delete_assign_base & - operator=(optional_delete_assign_base &&) noexcept = delete; -}; - -} // namespace detail - -/// \brief A tag type to represent an empty optional -struct nullopt_t { - struct do_not_use {}; - constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {} -}; -/// \brief Represents an empty optional -/// \synopsis static constexpr nullopt_t nullopt; -/// -/// *Examples*: -/// ``` -/// tl::optional a = tl::nullopt; -/// void foo (tl::optional); -/// foo(tl::nullopt); //pass an empty optional -/// ``` -static constexpr nullopt_t nullopt{nullopt_t::do_not_use{}, - nullopt_t::do_not_use{}}; - -class bad_optional_access : public std::exception { -public: - bad_optional_access() = default; - const char *what() const noexcept { return "Optional has no value"; } -}; - -/// An optional object is an object that contains the storage for another -/// object and manages the lifetime of this contained object, if any. The -/// contained object may be initialized after the optional object has been -/// initialized, and may be destroyed before the optional object has been -/// destroyed. The initialization state of the contained object is tracked by -/// the optional object. -template -class optional : private detail::optional_move_assign_base, - private detail::optional_delete_ctor_base, - private detail::optional_delete_assign_base { - using base = detail::optional_move_assign_base; - - static_assert(!std::is_same::value, - "instantiation of optional with in_place_t is ill-formed"); - static_assert(!std::is_same, nullopt_t>::value, - "instantiation of optional with nullopt_t is ill-formed"); - -public: -// The different versions for C++14 and 11 are needed because deduced return -// types are not SFINAE-safe. This provides better support for things like -// generic lambdas. C.f. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. \returns Let `U` be - /// the result of `std::invoke(std::forward(f), value())`. Returns a - /// `std::optional`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template constexpr auto and_then(F &&f) const & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template constexpr auto and_then(F &&f) const && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } -#endif -#else - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise the return value of - /// `std::invoke(std::forward(f), value())` is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr detail::invoke_result_t and_then(F &&f) const & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr detail::invoke_result_t and_then(F &&f) const && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } -#endif -#endif - -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template constexpr auto map(F &&f) &; - template TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & { - return optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) &&; - template TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&; - template constexpr auto map(F &&f) const & { - return optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&&; - template constexpr auto map(F &&f) const && { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template auto map(F &&f) &; - template - TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval(), - std::declval())) - map(F &&f) & { - return optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) &&; - template - TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval(), - std::declval())) - map(F &&f) && { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) const&; - template - constexpr decltype(optional_map_impl(std::declval(), - std::declval())) - map(F &&f) const & { - return optional_map_impl(*this, std::forward(f)); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group map - /// \synopsis template auto map(F &&f) const&&; - template - constexpr decltype(optional_map_impl(std::declval(), - std::declval())) - map(F &&f) const && { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - - /// \brief Calls `f` if the optional is empty - /// \requires `std::invoke_result_t` must be void or convertible to - /// `optional`. - /// \effects If `*this` has a value, returns `*this`. - /// Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns - /// `std::nullopt`. Otherwise, returns `std::forward(f)()`. - /// - /// \group or_else - /// \synopsis template optional or_else (F &&f) &; - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & { - return has_value() ? *this : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) &&; - template * = nullptr> - optional or_else(F &&f) && { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && { - return has_value() ? std::move(*this) : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) const &; - template * = nullptr> - optional or_else(F &&f) const & { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & { - return has_value() ? *this : std::forward(f)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \exclude - template * = nullptr> - optional or_else(F &&f) const && { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional or_else(F &&f) const && { - return has_value() ? std::move(*this) : std::forward(f)(); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise returns - /// `u`. - /// - /// \details If there is a value stored, then `f` is called with `**this` - /// and the value is returned. Otherwise `u` is returned. - /// - /// \group map_or - template U map_or(F &&f, U &&u) & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - - /// \group map_or - template U map_or(F &&f, U &&u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } - - /// \group map_or - template U map_or(F &&f, U &&u) const & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group map_or - template U map_or(F &&f, U &&u) const && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise calls - /// `u` and returns the result. - /// - /// \details If there is a value stored, then `f` is - /// called with `**this` and the value is returned. Otherwise - /// `std::forward(u)()` is returned. - /// - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) &; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// &&; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) const & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &&; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) const && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } -#endif - - /// \returns `u` if `*this` has a value, otherwise an empty optional. - template - constexpr optional::type> conjunction(U &&u) const { - using result = optional>; - return has_value() ? result{u} : result{nullopt}; - } - - /// \returns `rhs` if `*this` is empty, otherwise the current value. - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & { - return has_value() ? *this : rhs; - } - - /// \group disjunction - constexpr optional disjunction(const optional &rhs) const & { - return has_value() ? *this : rhs; - } - - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && { - return has_value() ? std::move(*this) : rhs; - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(const optional &rhs) const && { - return has_value() ? std::move(*this) : rhs; - } -#endif - - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - constexpr optional disjunction(optional &&rhs) const & { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && { - return has_value() ? std::move(*this) : std::move(rhs); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(optional &&rhs) const && { - return has_value() ? std::move(*this) : std::move(rhs); - } -#endif - - /// Takes the value out of the optional, leaving it empty - /// \group take - optional take() & { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() const & { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() && { - optional ret = std::move(*this); - reset(); - return ret; - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group take - optional take() const && { - optional ret = std::move(*this); - reset(); - return ret; - } -#endif - - using value_type = T; - - /// Constructs an optional that does not contain a value. - /// \group ctor_empty - constexpr optional() noexcept = default; - - /// \group ctor_empty - constexpr optional(nullopt_t) noexcept {} - - /// Copy constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) = default; - - /// Move constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default; - - /// Constructs the stored value in-place using the given arguments. - /// \group in_place - /// \synopsis template constexpr explicit optional(in_place_t, Args&&... args); - template - constexpr explicit optional( - detail::enable_if_t::value, in_place_t>, - Args &&... args) - : base(in_place, std::forward(args)...) {} - - /// \group in_place - /// \synopsis template \nconstexpr explicit optional(in_place_t, std::initializer_list&, Args&&... args); - template - TL_OPTIONAL_11_CONSTEXPR explicit optional( - detail::enable_if_t &, - Args &&...>::value, - in_place_t>, - std::initializer_list il, Args &&... args) { - this->construct(il, std::forward(args)...); - } - - /// Constructs the stored value with `u`. - /// \synopsis template constexpr optional(U &&u); - template < - class U = T, - detail::enable_if_t::value> * = nullptr, - detail::enable_forward_value * = nullptr> - constexpr optional(U &&u) : base(in_place, std::forward(u)) {} - - /// \exclude - template < - class U = T, - detail::enable_if_t::value> * = nullptr, - detail::enable_forward_value * = nullptr> - constexpr explicit optional(U &&u) : base(in_place, std::forward(u)) {} - - /// Converting copy constructor. - /// \synopsis template optional(const optional &rhs); - template < - class U, detail::enable_from_other * = nullptr, - detail::enable_if_t::value> * = nullptr> - optional(const optional &rhs) { - if (rhs.has_value()) { - this->construct(*rhs); - } - } - - /// \exclude - template * = nullptr, - detail::enable_if_t::value> * = - nullptr> - explicit optional(const optional &rhs) { - if (rhs.has_value()) { - this->construct(*rhs); - } - } - - /// Converting move constructor. - /// \synopsis template optional(optional &&rhs); - template < - class U, detail::enable_from_other * = nullptr, - detail::enable_if_t::value> * = nullptr> - optional(optional &&rhs) { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - } - - /// \exclude - template < - class U, detail::enable_from_other * = nullptr, - detail::enable_if_t::value> * = nullptr> - explicit optional(optional &&rhs) { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - } - - /// Destroys the stored value if there is one. - ~optional() = default; - - /// Assignment to empty. - /// - /// Destroys the current value if there is one. - optional &operator=(nullopt_t) noexcept { - if (has_value()) { - this->m_value.~T(); - this->m_has_value = false; - } - - return *this; - } - - /// Copy assignment. - /// - /// Copies the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - optional &operator=(const optional &rhs) = default; - - /// Move assignment. - /// - /// Moves the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - optional &operator=(optional &&rhs) = default; - - /// Assigns the stored value from `u`, destroying the old value if there was - /// one. - /// \synopsis optional &operator=(U &&u); - template * = nullptr> - optional &operator=(U &&u) { - if (has_value()) { - this->m_value = std::forward(u); - } else { - this->construct(std::forward(u)); - } - - return *this; - } - - /// Converting copy assignment operator. - /// - /// Copies the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - /// \synopsis optional &operator=(const optional & rhs); - template * = nullptr> - optional &operator=(const optional &rhs) { - if (has_value()) { - if (rhs.has_value()) { - this->m_value = *rhs; - } else { - this->hard_reset(); - } - } - - if (rhs.has_value()) { - this->construct(*rhs); - } - - return *this; - } - - // TODO check exception guarantee - /// Converting move assignment operator. - /// - /// Moves the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - /// \synopsis optional &operator=(optional && rhs); - template * = nullptr> - optional &operator=(optional &&rhs) { - if (has_value()) { - if (rhs.has_value()) { - this->m_value = std::move(*rhs); - } else { - this->hard_reset(); - } - } - - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - - return *this; - } - - /// Constructs the value in-place, destroying the current one if there is - /// one. - /// \group emplace - template T &emplace(Args &&... args) { - static_assert(std::is_constructible::value, - "T must be constructible with Args"); - - *this = nullopt; - this->construct(std::forward(args)...); - return value(); - } - - /// \group emplace - /// \synopsis template \nT& emplace(std::initializer_list il, Args &&... args); - template - detail::enable_if_t< - std::is_constructible &, Args &&...>::value, - T &> - emplace(std::initializer_list il, Args &&... args) { - *this = nullopt; - this->construct(il, std::forward(args)...); - return value(); - } - - /// Swaps this optional with the other. - /// - /// If neither optionals have a value, nothing happens. - /// If both have a value, the values are swapped. - /// If one has a value, it is moved to the other and the movee is left - /// valueless. - void - swap(optional &rhs) noexcept(std::is_nothrow_move_constructible::value - &&detail::is_nothrow_swappable::value) { - if (has_value()) { - if (rhs.has_value()) { - using std::swap; - swap(**this, *rhs); - } else { - new (std::addressof(rhs.m_value)) T(std::move(this->m_value)); - this->m_value.T::~T(); - } - } else if (rhs.has_value()) { - new (std::addressof(this->m_value)) T(std::move(rhs.m_value)); - rhs.m_value.T::~T(); - } - } - - /// \returns a pointer to the stored value - /// \requires a value is stored - /// \group pointer - /// \synopsis constexpr const T *operator->() const; - constexpr const T *operator->() const { - return std::addressof(this->m_value); - } - - /// \group pointer - /// \synopsis constexpr T *operator->(); - TL_OPTIONAL_11_CONSTEXPR T *operator->() { - return std::addressof(this->m_value); - } - - /// \returns the stored value - /// \requires a value is stored - /// \group deref - /// \synopsis constexpr T &operator*(); - TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; } - - /// \group deref - /// \synopsis constexpr const T &operator*() const; - constexpr const T &operator*() const & { return this->m_value; } - - /// \exclude - TL_OPTIONAL_11_CONSTEXPR T &&operator*() && { - return std::move(this->m_value); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \exclude - constexpr const T &&operator*() const && { return std::move(this->m_value); } -#endif - - /// \returns whether or not the optional has a value - /// \group has_value - constexpr bool has_value() const noexcept { return this->m_has_value; } - - /// \group has_value - constexpr explicit operator bool() const noexcept { - return this->m_has_value; - } - - /// \returns the contained value if there is one, otherwise throws - /// [bad_optional_access] - /// \group value - /// \synopsis constexpr T &value(); - TL_OPTIONAL_11_CONSTEXPR T &value() & { - if (has_value()) - return this->m_value; - throw bad_optional_access(); - } - /// \group value - /// \synopsis constexpr const T &value() const; - TL_OPTIONAL_11_CONSTEXPR const T &value() const & { - if (has_value()) - return this->m_value; - throw bad_optional_access(); - } - /// \exclude - TL_OPTIONAL_11_CONSTEXPR T &&value() && { - if (has_value()) - return std::move(this->m_value); - throw bad_optional_access(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \exclude - TL_OPTIONAL_11_CONSTEXPR const T &&value() const && { - if (has_value()) - return std::move(this->m_value); - throw bad_optional_access(); - } -#endif - - /// \returns the stored value if there is one, otherwise returns `u` - /// \group value_or - template constexpr T value_or(U &&u) const & { - static_assert(std::is_copy_constructible::value && - std::is_convertible::value, - "T must be copy constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// \group value_or - template TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && { - static_assert(std::is_move_constructible::value && - std::is_convertible::value, - "T must be move constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// Destroys the stored value if one exists, making the optional empty - void reset() noexcept { - if (has_value()) { - this->m_value.~T(); - this->m_has_value = false; - } - } -}; // namespace tl - -/// \group relop -/// \brief Compares two optional objects -/// \details If both optionals contain a value, they are compared with `T`s -/// relational operators. Otherwise `lhs` and `rhs` are equal only if they are -/// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs` -/// is not. -template -inline constexpr bool operator==(const optional &lhs, - const optional &rhs) { - return lhs.has_value() == rhs.has_value() && - (!lhs.has_value() || *lhs == *rhs); -} -/// \group relop -template -inline constexpr bool operator!=(const optional &lhs, - const optional &rhs) { - return lhs.has_value() != rhs.has_value() || - (lhs.has_value() && *lhs != *rhs); -} -/// \group relop -template -inline constexpr bool operator<(const optional &lhs, - const optional &rhs) { - return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs); -} -/// \group relop -template -inline constexpr bool operator>(const optional &lhs, - const optional &rhs) { - return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs); -} -/// \group relop -template -inline constexpr bool operator<=(const optional &lhs, - const optional &rhs) { - return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs); -} -/// \group relop -template -inline constexpr bool operator>=(const optional &lhs, - const optional &rhs) { - return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs); -} - -/// \group relop_nullopt -/// \brief Compares an optional to a `nullopt` -/// \details Equivalent to comparing the optional to an empty optional -template -inline constexpr bool operator==(const optional &lhs, nullopt_t) noexcept { - return !lhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator==(nullopt_t, const optional &rhs) noexcept { - return !rhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator!=(const optional &lhs, nullopt_t) noexcept { - return lhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator!=(nullopt_t, const optional &rhs) noexcept { - return rhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator<(const optional &, nullopt_t) noexcept { - return false; -} -/// \group relop_nullopt -template -inline constexpr bool operator<(nullopt_t, const optional &rhs) noexcept { - return rhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator<=(const optional &lhs, nullopt_t) noexcept { - return !lhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator<=(nullopt_t, const optional &) noexcept { - return true; -} -/// \group relop_nullopt -template -inline constexpr bool operator>(const optional &lhs, nullopt_t) noexcept { - return lhs.has_value(); -} -/// \group relop_nullopt -template -inline constexpr bool operator>(nullopt_t, const optional &) noexcept { - return false; -} -/// \group relop_nullopt -template -inline constexpr bool operator>=(const optional &, nullopt_t) noexcept { - return true; -} -/// \group relop_nullopt -template -inline constexpr bool operator>=(nullopt_t, const optional &rhs) noexcept { - return !rhs.has_value(); -} - -/// \group relop_t -/// \brief Compares the optional with a value. -/// \details If the optional has a value, it is compared with the other value -/// using `T`s relational operators. Otherwise, the optional is considered -/// less than the value. -template -inline constexpr bool operator==(const optional &lhs, const U &rhs) { - return lhs.has_value() ? *lhs == rhs : false; -} -/// \group relop_t -template -inline constexpr bool operator==(const U &lhs, const optional &rhs) { - return rhs.has_value() ? lhs == *rhs : false; -} -/// \group relop_t -template -inline constexpr bool operator!=(const optional &lhs, const U &rhs) { - return lhs.has_value() ? *lhs != rhs : true; -} -/// \group relop_t -template -inline constexpr bool operator!=(const U &lhs, const optional &rhs) { - return rhs.has_value() ? lhs != *rhs : true; -} -/// \group relop_t -template -inline constexpr bool operator<(const optional &lhs, const U &rhs) { - return lhs.has_value() ? *lhs < rhs : true; -} -/// \group relop_t -template -inline constexpr bool operator<(const U &lhs, const optional &rhs) { - return rhs.has_value() ? lhs < *rhs : false; -} -/// \group relop_t -template -inline constexpr bool operator<=(const optional &lhs, const U &rhs) { - return lhs.has_value() ? *lhs <= rhs : true; -} -/// \group relop_t -template -inline constexpr bool operator<=(const U &lhs, const optional &rhs) { - return rhs.has_value() ? lhs <= *rhs : false; -} -/// \group relop_t -template -inline constexpr bool operator>(const optional &lhs, const U &rhs) { - return lhs.has_value() ? *lhs > rhs : false; -} -/// \group relop_t -template -inline constexpr bool operator>(const U &lhs, const optional &rhs) { - return rhs.has_value() ? lhs > *rhs : true; -} -/// \group relop_t -template -inline constexpr bool operator>=(const optional &lhs, const U &rhs) { - return lhs.has_value() ? *lhs >= rhs : false; -} -/// \group relop_t -template -inline constexpr bool operator>=(const U &lhs, const optional &rhs) { - return rhs.has_value() ? lhs >= *rhs : true; -} - -/// \synopsis template \nvoid swap(optional &lhs, optional &rhs); -template ::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> -void swap(optional &lhs, - optional &rhs) noexcept(noexcept(lhs.swap(rhs))) { - return lhs.swap(rhs); -} - -namespace detail { -struct i_am_secret {}; -} // namespace detail - -template ::value, - detail::decay_t, T>> -inline constexpr optional make_optional(U &&v) { - return optional(std::forward(v)); -} - -template -inline constexpr optional make_optional(Args &&... args) { - return optional(in_place, std::forward(args)...); -} -template -inline constexpr optional make_optional(std::initializer_list il, - Args &&... args) { - return optional(in_place, il, std::forward(args)...); -} - -#if __cplusplus >= 201703L -template optional(T)->optional; -#endif - -/// \exclude -namespace detail { -#ifdef TL_OPTIONAL_CXX14 -template (), - *std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto optional_map_impl(Opt &&opt, F &&f) { - return opt.has_value() - ? detail::invoke(std::forward(f), *std::forward(opt)) - : optional(nullopt); -} - -template (), - *std::declval())), - detail::enable_if_t::value> * = nullptr> -auto optional_map_impl(Opt &&opt, F &&f) { - if (opt.has_value()) { - detail::invoke(std::forward(f), *std::forward(opt)); - return make_optional(monostate{}); - } - - return optional(nullopt); -} -#else -template (), - *std::declval())), - detail::enable_if_t::value> * = nullptr> - -constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional { - return opt.has_value() - ? detail::invoke(std::forward(f), *std::forward(opt)) - : optional(nullopt); -} - -template (), - *std::declval())), - detail::enable_if_t::value> * = nullptr> - -auto optional_map_impl(Opt &&opt, F &&f) -> optional { - if (opt.has_value()) { - detail::invoke(std::forward(f), *std::forward(opt)); - return monostate{}; - } - - return nullopt; -} -#endif -} // namespace detail - -/// Specialization for when `T` is a reference. `optional` acts similarly -/// to a `T*`, but provides more operations and shows intent more clearly. -/// -/// *Examples*: -/// -/// ``` -/// int i = 42; -/// tl::optional o = i; -/// *o == 42; //true -/// i = 12; -/// *o = 12; //true -/// &*o == &i; //true -/// ``` -/// -/// Assignment has rebind semantics rather than assign-through semantics: -/// -/// ``` -/// int j = 8; -/// o = j; -/// -/// &*o == &j; //true -/// ``` -template class optional { -public: -// The different versions for C++14 and 11 are needed because deduced return -// types are not SFINAE-safe. This provides better support for things like -// generic lambdas. C.f. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. \returns Let `U` be - /// the result of `std::invoke(std::forward(f), value())`. Returns a - /// `std::optional`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template constexpr auto and_then(F &&f) const & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template constexpr auto and_then(F &&f) const && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } -#endif -#else - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. \returns Let `U` be - /// the result of `std::invoke(std::forward(f), value())`. Returns a - /// `std::optional`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr detail::invoke_result_t and_then(F &&f) const & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr detail::invoke_result_t and_then(F &&f) const && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } -#endif -#endif - -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template constexpr auto map(F &&f) &; - template TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) &&; - template TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&; - template constexpr auto map(F &&f) const & { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&&; - template constexpr auto map(F &&f) const && { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template auto map(F &&f) &; - template - TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval(), - std::declval())) - map(F &&f) & { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) &&; - template - TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval(), - std::declval())) - map(F &&f) && { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) const&; - template - constexpr decltype(detail::optional_map_impl(std::declval(), - std::declval())) - map(F &&f) const & { - return detail::optional_map_impl(*this, std::forward(f)); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group map - /// \synopsis template auto map(F &&f) const&&; - template - constexpr decltype(detail::optional_map_impl(std::declval(), - std::declval())) - map(F &&f) const && { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - - /// \brief Calls `f` if the optional is empty - /// \requires `std::invoke_result_t` must be void or convertible to - /// `optional`. \effects If `*this` has a value, returns `*this`. - /// Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns - /// `std::nullopt`. Otherwise, returns `std::forward(f)()`. - /// - /// \group or_else - /// \synopsis template optional or_else (F &&f) &; - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & { - return has_value() ? *this : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) &&; - template * = nullptr> - optional or_else(F &&f) && { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && { - return has_value() ? std::move(*this) : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) const &; - template * = nullptr> - optional or_else(F &&f) const & { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & { - return has_value() ? *this : std::forward(f)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \exclude - template * = nullptr> - optional or_else(F &&f) const && { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional or_else(F &&f) const && { - return has_value() ? std::move(*this) : std::forward(f)(); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise returns - /// `u`. - /// - /// \details If there is a value stored, then `f` is called with `**this` - /// and the value is returned. Otherwise `u` is returned. - /// - /// \group map_or - template U map_or(F &&f, U &&u) & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - - /// \group map_or - template U map_or(F &&f, U &&u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } - - /// \group map_or - template U map_or(F &&f, U &&u) const & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group map_or - template U map_or(F &&f, U &&u) const && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise calls - /// `u` and returns the result. - /// - /// \details If there is a value stored, then `f` is - /// called with `**this` and the value is returned. Otherwise - /// `std::forward(u)()` is returned. - /// - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) &; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// &&; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) const & { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &&; - template - detail::invoke_result_t map_or_else(F &&f, U &&u) const && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } -#endif - - /// \returns `u` if `*this` has a value, otherwise an empty optional. - template - constexpr optional::type> conjunction(U &&u) const { - using result = optional>; - return has_value() ? result{u} : result{nullopt}; - } - - /// \returns `rhs` if `*this` is empty, otherwise the current value. - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & { - return has_value() ? *this : rhs; - } - - /// \group disjunction - constexpr optional disjunction(const optional &rhs) const & { - return has_value() ? *this : rhs; - } - - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && { - return has_value() ? std::move(*this) : rhs; - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(const optional &rhs) const && { - return has_value() ? std::move(*this) : rhs; - } -#endif - - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - constexpr optional disjunction(optional &&rhs) const & { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && { - return has_value() ? std::move(*this) : std::move(rhs); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(optional &&rhs) const && { - return has_value() ? std::move(*this) : std::move(rhs); - } -#endif - - /// Takes the value out of the optional, leaving it empty - /// \group take - optional take() & { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() const & { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() && { - optional ret = std::move(*this); - reset(); - return ret; - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - /// \group take - optional take() const && { - optional ret = std::move(*this); - reset(); - return ret; - } -#endif - - using value_type = T &; - - /// Constructs an optional that does not contain a value. - /// \group ctor_empty - constexpr optional() noexcept : m_value(nullptr) {} - - /// \group ctor_empty - constexpr optional(nullopt_t) noexcept : m_value(nullptr) {} - - /// Copy constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default; - - /// Move constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default; - - /// Constructs the stored value with `u`. - /// \synopsis template constexpr optional(U &&u); - template >::value> - * = nullptr> - constexpr optional(U &&u) : m_value(std::addressof(u)) { - static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); - } - - /// \exclude - template - constexpr explicit optional(const optional &rhs) : optional(*rhs) {} - - /// No-op - ~optional() = default; - - /// Assignment to empty. - /// - /// Destroys the current value if there is one. - optional &operator=(nullopt_t) noexcept { - m_value = nullptr; - return *this; - } - - /// Copy assignment. - /// - /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise - /// resets the stored value in `*this`. - optional &operator=(const optional &rhs) = default; - - /// Rebinds this optional to `u`. - /// - /// \requires `U` must be an lvalue reference. - /// \synopsis optional &operator=(U &&u); - template >::value> - * = nullptr> - optional &operator=(U &&u) { - static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); - m_value = std::addressof(u); - return *this; - } - - /// Converting copy assignment operator. - /// - /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise - /// resets the stored value in `*this`. - template optional &operator=(const optional &rhs) { - m_value = std::addressof(rhs.value()); - return *this; - } - - /// Constructs the value in-place, destroying the current one if there is - /// one. - /// - /// \group emplace - template T &emplace(Args &&... args) noexcept { - static_assert(std::is_constructible::value, - "T must be constructible with Args"); - - *this = nullopt; - this->construct(std::forward(args)...); - return value(); - } - - /// Swaps this optional with the other. - /// - /// If neither optionals have a value, nothing happens. - /// If both have a value, the values are swapped. - /// If one has a value, it is moved to the other and the movee is left - /// valueless. - void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); } - - /// \returns a pointer to the stored value - /// \requires a value is stored - /// \group pointer - /// \synopsis constexpr const T *operator->() const; - constexpr const T *operator->() const { return m_value; } - - /// \group pointer - /// \synopsis constexpr T *operator->(); - TL_OPTIONAL_11_CONSTEXPR T *operator->() { return m_value; } - - /// \returns the stored value - /// \requires a value is stored - /// \group deref - /// \synopsis constexpr T &operator*(); - TL_OPTIONAL_11_CONSTEXPR T &operator*() { return *m_value; } - - /// \group deref - /// \synopsis constexpr const T &operator*() const; - constexpr const T &operator*() const { return *m_value; } - - /// \returns whether or not the optional has a value - /// \group has_value - constexpr bool has_value() const noexcept { return m_value != nullptr; } - - /// \group has_value - constexpr explicit operator bool() const noexcept { - return m_value != nullptr; - } - - /// \returns the contained value if there is one, otherwise throws - /// [bad_optional_access] - /// \group value - /// synopsis constexpr T &value(); - TL_OPTIONAL_11_CONSTEXPR T &value() { - if (has_value()) - return *m_value; - throw bad_optional_access(); - } - /// \group value - /// \synopsis constexpr const T &value() const; - TL_OPTIONAL_11_CONSTEXPR const T &value() const { - if (has_value()) - return *m_value; - throw bad_optional_access(); - } - - /// \returns the stored value if there is one, otherwise returns `u` - /// \group value_or - template constexpr T value_or(U &&u) const & { - static_assert(std::is_copy_constructible::value && - std::is_convertible::value, - "T must be copy constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// \group value_or - template TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && { - static_assert(std::is_move_constructible::value && - std::is_convertible::value, - "T must be move constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// Destroys the stored value if one exists, making the optional empty - void reset() noexcept { m_value = nullptr; } - -private: - T *m_value; -}; // namespace tl - - - -} // namespace tl - -namespace std { -// TODO SFINAE -template struct hash> { - ::std::size_t operator()(const tl::optional &o) const { - if (!o.has_value()) - return 0; - - return std::hash>()(*o); - } -}; -} // namespace std - -#endif diff --git a/src/search/search_engines/eager_search.cc b/src/search/search_engines/eager_search.cc index 193825ef2c..d37f4a97e5 100644 --- a/src/search/search_engines/eager_search.cc +++ b/src/search/search_engines/eager_search.cc @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include using namespace std; @@ -108,7 +108,7 @@ void EagerSearch::print_statistics() const { } SearchStatus EagerSearch::step() { - tl::optional node; + optional node; while (true) { if (open_list->empty()) { log << "Completely explored state space -- no solution!" << endl;