Merge in changes from master

This commit is contained in:
Simon Brand
2019-04-26 13:33:10 +01:00
parent f6c92068ac
commit d721366fe2
8 changed files with 164 additions and 22 deletions

View File

@@ -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
View 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')

View 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
View 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
View 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);
}

View File

@@ -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
View 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);
}

View File

@@ -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