mirror of
https://github.com/TartanLlama/expected.git
synced 2025-08-01 01:44:30 +02:00
Merge in changes from master
This commit is contained in:
@@ -254,4 +254,4 @@ install:
|
||||
- if [ "$CXX" = "clang++" ]; then export CXX="$COMPILER -stdlib=libc++"; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="$COMPILER"; fi
|
||||
|
||||
script: mkdir build && cd build && cmake .. && make && ./tests
|
||||
script: mkdir build && cd build && cmake -DCXXSTD=$CXXSTD .. && make && ./tests
|
||||
|
34
conanfile.py
Normal file
34
conanfile.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from conans import ConanFile, CMake, tools
|
||||
|
||||
class ExpectedConan(ConanFile):
|
||||
name = "expected"
|
||||
version = "master"
|
||||
license = "CC0-1.0"
|
||||
author = "Simon Brand <tartanllama@gmail.com>"
|
||||
url = "https://github.com/TartanLlama/expected"
|
||||
description = "C++11/14/17 std::expected with functional-style extensions"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "cmake"
|
||||
exports_sources = "*"
|
||||
|
||||
def source(self):
|
||||
tools.replace_in_file('CMakeLists.txt', 'project(expected)',
|
||||
'''project(expected)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
''')
|
||||
|
||||
def configure_cmake(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
return cmake
|
||||
|
||||
def build(self):
|
||||
cmake = self.configure_cmake()
|
||||
cmake.build()
|
||||
|
||||
if not tools.cross_building(self.settings):
|
||||
self.run('%s/bin/tests' % self.build_folder)
|
||||
|
||||
def package(self):
|
||||
self.copy('*.hpp', dst='include/tl', src='tl')
|
14
test_package/CMakeLists.txt
Normal file
14
test_package/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(PackageTest CXX)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example ${CONAN_LIBS})
|
||||
|
||||
# CTest is a testing tool that can be used to test your project.
|
||||
# enable_testing()
|
||||
# add_test(NAME example
|
||||
# WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
# COMMAND example)
|
25
test_package/conanfile.py
Normal file
25
test_package/conanfile.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
|
||||
from conans import ConanFile, CMake, tools
|
||||
|
||||
|
||||
class ExpectedTestConan(ConanFile):
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "cmake"
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
# Current dir is "test_package/build/<build_id>" and CMakeLists.txt is
|
||||
# in "test_package"
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def imports(self):
|
||||
self.copy("*.dll", dst="bin", src="bin")
|
||||
self.copy("*.dylib*", dst="bin", src="lib")
|
||||
self.copy('*.so*', dst='bin', src='lib')
|
||||
|
||||
def test(self):
|
||||
if not tools.cross_building(self.settings):
|
||||
os.chdir("bin")
|
||||
self.run(".%sexample" % os.sep)
|
16
test_package/example.cpp
Normal file
16
test_package/example.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
tl::expected<int, const char*> maybe_do_something(int i) {
|
||||
if (i < 5) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return tl::make_unexpected("Uh oh");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
(void)argv;
|
||||
|
||||
return maybe_do_something(0).value_or(-1);
|
||||
}
|
@@ -105,4 +105,25 @@ TEST_CASE("Issue 42", "[issues.42]") {
|
||||
TEST_CASE("Issue 43", "[issues.43]") {
|
||||
auto result = tl::expected<void, std::string>{};
|
||||
result = tl::make_unexpected(std::string{ "foo" });
|
||||
}
|
||||
}
|
||||
|
||||
#if !(__GNUC__ <= 5)
|
||||
#include <memory>
|
||||
|
||||
using MaybeDataPtr = tl::expected<int, std::unique_ptr<int>>;
|
||||
|
||||
MaybeDataPtr test(int i) noexcept
|
||||
{
|
||||
return std::move(i);
|
||||
}
|
||||
|
||||
MaybeDataPtr test2(int i) noexcept
|
||||
{
|
||||
return std::move(i);
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 49", "[issues.49]") {
|
||||
auto m = test(10)
|
||||
.and_then(test2);
|
||||
}
|
||||
#endif
|
32
tests/test.cpp
Normal file
32
tests/test.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
struct no_throw {
|
||||
no_throw(std::string i) : i(i) {}
|
||||
std::string i;
|
||||
};
|
||||
struct canthrow_move {
|
||||
canthrow_move(std::string i) : i(i) {}
|
||||
canthrow_move(canthrow_move const &) = default;
|
||||
canthrow_move(canthrow_move &&other) noexcept(false) : i(other.i) {}
|
||||
canthrow_move &operator=(canthrow_move &&) = default;
|
||||
std::string i;
|
||||
};
|
||||
|
||||
bool should_throw = false;
|
||||
struct willthrow_move {
|
||||
willthrow_move(std::string i) : i(i) {}
|
||||
willthrow_move(willthrow_move const &) = default;
|
||||
willthrow_move(willthrow_move &&other) : i(other.i) {
|
||||
if (should_throw)
|
||||
throw 0;
|
||||
}
|
||||
willthrow_move &operator=(willthrow_move &&) = default;
|
||||
std::string i;
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string s2 = "zyxwvutsrqponmlkjihgfedcbaxxx";
|
||||
tl::expected<no_throw, willthrow_move> a{s1};
|
||||
tl::expected<no_throw, willthrow_move> b{tl::unexpect, s2};
|
||||
should_throw = 1;
|
||||
swap(a, b);
|
||||
}
|
@@ -460,9 +460,9 @@ struct expected_storage_base {
|
||||
}
|
||||
}
|
||||
union {
|
||||
char m_no_init;
|
||||
T m_val;
|
||||
unexpected<E> m_unexpect;
|
||||
char m_no_init;
|
||||
};
|
||||
bool m_has_val;
|
||||
};
|
||||
@@ -501,9 +501,9 @@ template <class T, class E> struct expected_storage_base<T, E, true, true> {
|
||||
|
||||
~expected_storage_base() = default;
|
||||
union {
|
||||
char m_no_init;
|
||||
T m_val;
|
||||
unexpected<E> m_unexpect;
|
||||
char m_no_init;
|
||||
};
|
||||
bool m_has_val;
|
||||
};
|
||||
@@ -547,9 +547,9 @@ template <class T, class E> struct expected_storage_base<T, E, true, false> {
|
||||
}
|
||||
|
||||
union {
|
||||
char m_no_init;
|
||||
T m_val;
|
||||
unexpected<E> m_unexpect;
|
||||
char m_no_init;
|
||||
};
|
||||
bool m_has_val;
|
||||
};
|
||||
@@ -591,9 +591,9 @@ template <class T, class E> struct expected_storage_base<T, E, false, true> {
|
||||
}
|
||||
}
|
||||
union {
|
||||
char m_no_init;
|
||||
T m_val;
|
||||
unexpected<E> m_unexpect;
|
||||
char m_no_init;
|
||||
};
|
||||
bool m_has_val;
|
||||
};
|
||||
@@ -622,8 +622,8 @@ template <class E> struct expected_storage_base<void, E, false, true> {
|
||||
~expected_storage_base() = default;
|
||||
struct dummy {};
|
||||
union {
|
||||
dummy m_val;
|
||||
unexpected<E> m_unexpect;
|
||||
dummy m_val;
|
||||
};
|
||||
bool m_has_val;
|
||||
};
|
||||
@@ -656,8 +656,8 @@ template <class E> struct expected_storage_base<void, E, false, false> {
|
||||
}
|
||||
|
||||
union {
|
||||
char m_dummy;
|
||||
unexpected<E> m_unexpect;
|
||||
char m_dummy;
|
||||
};
|
||||
bool m_has_val;
|
||||
};
|
||||
@@ -837,7 +837,7 @@ struct expected_operations_base : expected_storage_base<T, E> {
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr void destroy_val() {
|
||||
TL_EXPECTED_11_CONSTEXPR void destroy_val() {
|
||||
get().~T();
|
||||
}
|
||||
};
|
||||
@@ -892,7 +892,7 @@ struct expected_operations_base<void, E> : expected_storage_base<void, E> {
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr void destroy_val() {
|
||||
TL_EXPECTED_11_CONSTEXPR void destroy_val() {
|
||||
//no-op
|
||||
}
|
||||
};
|
||||
@@ -1229,17 +1229,17 @@ class expected : private detail::expected_move_assign_base<T, E>,
|
||||
|
||||
template <class U = T,
|
||||
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||
U &val() {
|
||||
TL_EXPECTED_11_CONSTEXPR U &val() {
|
||||
return this->m_val;
|
||||
}
|
||||
unexpected<E> &err() { return this->m_unexpect; }
|
||||
TL_EXPECTED_11_CONSTEXPR unexpected<E> &err() { return this->m_unexpect; }
|
||||
|
||||
template <class U = T,
|
||||
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||
const U &val() const {
|
||||
constexpr const U &val() const {
|
||||
return this->m_val;
|
||||
}
|
||||
const unexpected<E> &err() const { return this->m_unexpect; }
|
||||
constexpr const unexpected<E> &err() const { return this->m_unexpect; }
|
||||
|
||||
using impl_base = detail::expected_move_assign_base<T, E>;
|
||||
using ctor_base = detail::expected_default_ctor_base<T, E>;
|
||||
@@ -1296,7 +1296,7 @@ public:
|
||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
||||
template <class F>
|
||||
TL_EXPECTED_11_CONSTEXPR auto
|
||||
and_then(F &&f) & -> decltype(and_then_impl(*this, std::forward<F>(f))) {
|
||||
and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected&>(), std::forward<F>(f))) {
|
||||
return and_then_impl(*this, std::forward<F>(f));
|
||||
}
|
||||
|
||||
@@ -1304,7 +1304,7 @@ public:
|
||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
||||
template <class F>
|
||||
TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(
|
||||
and_then_impl(std::move(*this), std::forward<F>(f))) {
|
||||
and_then_impl(std::declval<expected&&>(), std::forward<F>(f))) {
|
||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
||||
}
|
||||
|
||||
@@ -1312,7 +1312,7 @@ public:
|
||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
||||
template <class F>
|
||||
constexpr auto and_then(F &&f) const & -> decltype(
|
||||
and_then_impl(*this, std::forward<F>(f))) {
|
||||
and_then_impl(std::declval<expected const&>(), std::forward<F>(f))) {
|
||||
return and_then_impl(*this, std::forward<F>(f));
|
||||
}
|
||||
|
||||
@@ -1321,7 +1321,7 @@ public:
|
||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
||||
template <class F>
|
||||
constexpr auto and_then(F &&f) const && -> decltype(
|
||||
and_then_impl(std::move(*this), std::forward<F>(f))) {
|
||||
and_then_impl(std::declval<expected const&&>(), std::forward<F>(f))) {
|
||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
||||
}
|
||||
#endif
|
||||
@@ -2053,7 +2053,7 @@ constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
||||
|
||||
return exp.has_value()
|
||||
? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
||||
: Ret(unexpect, exp.error());
|
||||
: Ret(unexpect, std::forward<Exp>(exp).error());
|
||||
}
|
||||
|
||||
template <class Exp, class F,
|
||||
@@ -2063,7 +2063,7 @@ constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
||||
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
||||
|
||||
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
||||
: Ret(unexpect, exp.error());
|
||||
: Ret(unexpect, std::forward<Exp>(exp).error());
|
||||
}
|
||||
#else
|
||||
template <class> struct TC;
|
||||
@@ -2076,7 +2076,7 @@ auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
||||
|
||||
return exp.has_value()
|
||||
? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
||||
: Ret(unexpect, exp.error());
|
||||
: Ret(unexpect, std::forward<Exp>(exp).error());
|
||||
}
|
||||
|
||||
template <class Exp, class F,
|
||||
@@ -2086,7 +2086,7 @@ constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
||||
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
||||
|
||||
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
||||
: Ret(unexpect, exp.error());
|
||||
: Ret(unexpect, std::forward<Exp>(exp).error());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user