Do CMake properly

This commit is contained in:
Simon Brand
2019-05-01 12:15:40 +01:00
parent 2c9780949d
commit 90ed23a4e4
19 changed files with 285 additions and 276 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "cmake/tl-cmake"]
path = cmake/tl-cmake
url = https://github.com/TartanLlama/tl-cmake.git

View File

@ -1,12 +1,14 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.8)
project(expected)
project(tl-expected VERSION 1.0.0 LANGUAGES CXX)
option(EXPECTED_ENABLE_TESTS "Enable tests." ON)
add_library(expected INTERFACE)
target_sources(expected INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/tl/expected.hpp)
target_include_directories(expected INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/tl)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/tl-cmake" ${CMAKE_MODULE_PATH})
include(add-tl)
tl_add_library(expected SOURCES
include/tl/expected.hpp)
# Prepare "Catch" library for other executables
set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test)

1
cmake/tl-cmake Submodule

Submodule cmake/tl-cmake added at 284c6a3f0f

View File

@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/tl-expected-targets.cmake")

View File

@ -12,8 +12,8 @@ class ExpectedConan(ConanFile):
exports_sources = "*"
def source(self):
tools.replace_in_file('CMakeLists.txt', 'project(expected)',
'''project(expected)
tools.replace_in_file('CMakeLists.txt', 'project(tl-expected)',
'''project(tl-expected)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
''')
@ -31,4 +31,4 @@ conan_basic_setup()
self.run('%s/bin/tests' % self.build_folder)
def package(self):
self.copy('*.hpp', dst='include/tl', src='tl')
self.copy('*.hpp', dst='include/tl', src='include/tl')

BIN
include/tl/expected.hpp.gch Normal file

Binary file not shown.

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
TEST_CASE("Simple assignment", "[assignment.simple]") {
tl::expected<int, int> e1 = 42;

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
#include <string>

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
TEST_CASE("Constexpr", "[constexpr]") {
//TODO

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
#include <vector>
#include <type_traits>

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
#include <memory>
#include <vector>
#include <tuple>

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)

View File

@ -1,129 +1,129 @@
#include "catch.hpp"
#include "expected.hpp"
#include <string>
using std::string;
tl::expected<int, string> getInt3(int val) { return val; }
tl::expected<int, string> getInt2(int val) { return val; }
tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }
TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }
tl::expected<int, int> operation1() { return 42; }
tl::expected<std::string, int> operation2(int const val) { return "Bananas"; }
TEST_CASE("Issue 17", "[issues.17]") {
auto const intermediate_result = operation1();
intermediate_result.and_then(operation2);
}
struct a {};
struct b : a {};
auto doit() -> tl::expected<std::unique_ptr<b>, int> {
return tl::make_unexpected(0);
}
TEST_CASE("Issue 23", "[issues.23]") {
tl::expected<std::unique_ptr<a>, int> msg = doit();
REQUIRE(!msg.has_value());
}
TEST_CASE("Issue 26", "[issues.26]") {
tl::expected<a, int> exp = tl::expected<b, int>(tl::unexpect, 0);
REQUIRE(!exp.has_value());
}
struct foo {
foo() = default;
foo(foo &) = delete;
foo(foo &&){};
};
TEST_CASE("Issue 29", "[issues.29]") {
std::vector<foo> v;
v.emplace_back();
tl::expected<std::vector<foo>, int> ov = std::move(v);
REQUIRE(ov->size() == 1);
}
tl::expected<int, std::string> error() {
return tl::make_unexpected(std::string("error1 "));
}
std::string maperror(std::string s) { return s + "maperror "; }
TEST_CASE("Issue 30", "[issues.30]") {
error().map_error(maperror);
}
struct i31{
int i;
};
TEST_CASE("Issue 31", "[issues.31]") {
const tl::expected<i31, int> a = i31{42};
a->i;
tl::expected< void, std::string > result;
tl::expected< void, std::string > result2 = result;
result2 = result;
}
TEST_CASE("Issue 33", "[issues.33]") {
tl::expected<void, int> res {tl::unexpect, 0};
REQUIRE(!res);
res = res.map_error([](int i) { return 42; });
REQUIRE(res.error() == 42);
}
tl::expected<void, std::string> voidWork() { return {}; }
tl::expected<int, std::string> work2() { return 42; }
void errorhandling(std::string){}
TEST_CASE("Issue 34", "[issues.34]") {
tl::expected <int, std::string> result = voidWork ()
.and_then (work2);
result.map_error ([&] (std::string result) {errorhandling (result);});
}
struct non_copyable {
non_copyable(non_copyable&&) = default;
non_copyable(non_copyable const&) = delete;
non_copyable() = default;
};
TEST_CASE("Issue 42", "[issues.42]") {
tl::expected<non_copyable,int>{}.map([](non_copyable) {});
}
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);
}
#include "catch.hpp"
#include <tl/expected.hpp>
#include <string>
using std::string;
tl::expected<int, string> getInt3(int val) { return val; }
tl::expected<int, string> getInt2(int val) { return val; }
tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }
TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }
tl::expected<int, int> operation1() { return 42; }
tl::expected<std::string, int> operation2(int const val) { return "Bananas"; }
TEST_CASE("Issue 17", "[issues.17]") {
auto const intermediate_result = operation1();
intermediate_result.and_then(operation2);
}
struct a {};
struct b : a {};
auto doit() -> tl::expected<std::unique_ptr<b>, int> {
return tl::make_unexpected(0);
}
TEST_CASE("Issue 23", "[issues.23]") {
tl::expected<std::unique_ptr<a>, int> msg = doit();
REQUIRE(!msg.has_value());
}
TEST_CASE("Issue 26", "[issues.26]") {
tl::expected<a, int> exp = tl::expected<b, int>(tl::unexpect, 0);
REQUIRE(!exp.has_value());
}
struct foo {
foo() = default;
foo(foo &) = delete;
foo(foo &&){};
};
TEST_CASE("Issue 29", "[issues.29]") {
std::vector<foo> v;
v.emplace_back();
tl::expected<std::vector<foo>, int> ov = std::move(v);
REQUIRE(ov->size() == 1);
}
tl::expected<int, std::string> error() {
return tl::make_unexpected(std::string("error1 "));
}
std::string maperror(std::string s) { return s + "maperror "; }
TEST_CASE("Issue 30", "[issues.30]") {
error().map_error(maperror);
}
struct i31{
int i;
};
TEST_CASE("Issue 31", "[issues.31]") {
const tl::expected<i31, int> a = i31{42};
a->i;
tl::expected< void, std::string > result;
tl::expected< void, std::string > result2 = result;
result2 = result;
}
TEST_CASE("Issue 33", "[issues.33]") {
tl::expected<void, int> res {tl::unexpect, 0};
REQUIRE(!res);
res = res.map_error([](int i) { return 42; });
REQUIRE(res.error() == 42);
}
tl::expected<void, std::string> voidWork() { return {}; }
tl::expected<int, std::string> work2() { return 42; }
void errorhandling(std::string){}
TEST_CASE("Issue 34", "[issues.34]") {
tl::expected <int, std::string> result = voidWork ()
.and_then (work2);
result.map_error ([&] (std::string result) {errorhandling (result);});
}
struct non_copyable {
non_copyable(non_copyable&&) = default;
non_copyable(non_copyable const&) = delete;
non_copyable() = default;
};
TEST_CASE("Issue 42", "[issues.42]") {
tl::expected<non_copyable,int>{}.map([](non_copyable) {});
}
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

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
TEST_CASE("Noexcept", "[noexcept]") {
//TODO

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
struct move_detector {
move_detector() = default;

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "expected.hpp"
#include <tl/expected.hpp>
TEST_CASE("Relational operators", "[relops]") {
//TODO

View File

@ -1,101 +1,101 @@
#include "catch.hpp"
#include "expected.hpp"
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;
};
static_assert(tl::detail::is_swappable<no_throw>::value, "");
template <class T1, class T2> void swap_test() {
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
std::string s2 = "zyxwvutsrqponmlkjihgfedcba";
tl::expected<T1, T2> a{s1};
tl::expected<T1, T2> b{s2};
swap(a, b);
REQUIRE(a->i == s2);
REQUIRE(b->i == s1);
a = s1;
b = tl::unexpected<T2>(s2);
swap(a, b);
REQUIRE(a.error().i == s2);
REQUIRE(b->i == s1);
a = tl::unexpected<T2>(s1);
b = s2;
swap(a, b);
REQUIRE(a->i == s2);
REQUIRE(b.error().i == s1);
a = tl::unexpected<T2>(s1);
b = tl::unexpected<T2>(s2);
swap(a, b);
REQUIRE(a.error().i == s2);
REQUIRE(b.error().i == s1);
a = s1;
b = s2;
a.swap(b);
REQUIRE(a->i == s2);
REQUIRE(b->i == s1);
a = s1;
b = tl::unexpected<T2>(s2);
a.swap(b);
REQUIRE(a.error().i == s2);
REQUIRE(b->i == s1);
a = tl::unexpected<T2>(s1);
b = s2;
a.swap(b);
REQUIRE(a->i == s2);
REQUIRE(b.error().i == s1);
a = tl::unexpected<T2>(s1);
b = tl::unexpected<T2>(s2);
a.swap(b);
REQUIRE(a.error().i == s2);
REQUIRE(b.error().i == s1);
}
TEST_CASE("swap") {
swap_test<no_throw, no_throw>();
swap_test<no_throw, canthrow_move>();
swap_test<canthrow_move, no_throw>();
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;
#ifdef _MSC_VER
//this seems to break catch on GCC and Clang
REQUIRE_THROWS(swap(a, b));
#endif
REQUIRE(a->i == s1);
REQUIRE(b.error().i == s2);
#include "catch.hpp"
#include <tl/expected.hpp>
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;
};
static_assert(tl::detail::is_swappable<no_throw>::value, "");
template <class T1, class T2> void swap_test() {
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
std::string s2 = "zyxwvutsrqponmlkjihgfedcba";
tl::expected<T1, T2> a{s1};
tl::expected<T1, T2> b{s2};
swap(a, b);
REQUIRE(a->i == s2);
REQUIRE(b->i == s1);
a = s1;
b = tl::unexpected<T2>(s2);
swap(a, b);
REQUIRE(a.error().i == s2);
REQUIRE(b->i == s1);
a = tl::unexpected<T2>(s1);
b = s2;
swap(a, b);
REQUIRE(a->i == s2);
REQUIRE(b.error().i == s1);
a = tl::unexpected<T2>(s1);
b = tl::unexpected<T2>(s2);
swap(a, b);
REQUIRE(a.error().i == s2);
REQUIRE(b.error().i == s1);
a = s1;
b = s2;
a.swap(b);
REQUIRE(a->i == s2);
REQUIRE(b->i == s1);
a = s1;
b = tl::unexpected<T2>(s2);
a.swap(b);
REQUIRE(a.error().i == s2);
REQUIRE(b->i == s1);
a = tl::unexpected<T2>(s1);
b = s2;
a.swap(b);
REQUIRE(a->i == s2);
REQUIRE(b.error().i == s1);
a = tl::unexpected<T2>(s1);
b = tl::unexpected<T2>(s2);
a.swap(b);
REQUIRE(a.error().i == s2);
REQUIRE(b.error().i == s1);
}
TEST_CASE("swap") {
swap_test<no_throw, no_throw>();
swap_test<no_throw, canthrow_move>();
swap_test<canthrow_move, no_throw>();
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;
#ifdef _MSC_VER
//this seems to break catch on GCC and Clang
REQUIRE_THROWS(swap(a, b));
#endif
REQUIRE(a->i == s1);
REQUIRE(b.error().i == s2);
}

View File

@ -1,32 +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);
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);
}