-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
132167c
commit 96662e1
Showing
7 changed files
with
198 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# ignore conan.io package test buildtree | ||
test_package/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,44 +8,44 @@ matrix: | |
apt: | ||
sources: ['ubuntu-toolchain-r-test', 'boost-latest'] | ||
packages: ['g++-5', 'libboost1.55-all-dev'] | ||
env: TOOLSET=clang++ BUILD_TYPE='Release' BUILD_DOCS=1 | ||
env: TOOLSET=clang++ TOOLSET_C=clang BUILD_TYPE='Release' BUILD_DOCS=1 | ||
|
||
- os: linux | ||
compiler: gcc | ||
addons: | ||
apt: | ||
sources: ['ubuntu-toolchain-r-test'] | ||
packages: ['g++-4.8'] | ||
env: TOOLSET=g++-4.8 BUILD_TYPE='Debug' BUILD_DOCS=0 | ||
env: TOOLSET=g++-4.8 TOOLSET_C=gcc-4.8 BUILD_TYPE='Debug' BUILD_DOCS=0 | ||
- os: linux | ||
compiler: gcc | ||
addons: | ||
apt: | ||
sources: ['ubuntu-toolchain-r-test'] | ||
packages: ['g++-4.8'] | ||
env: TOOLSET=g++-4.8 BUILD_TYPE='Release' BUILD_DOCS=0 | ||
env: TOOLSET=g++-4.8 TOOLSET_C=gcc-4.8 BUILD_TYPE='Release' BUILD_DOCS=0 | ||
|
||
- os: linux | ||
compiler: gcc | ||
addons: | ||
apt: | ||
sources: ['ubuntu-toolchain-r-test'] | ||
packages: ['g++-5'] | ||
env: TOOLSET=g++-5 BUILD_TYPE='Debug' BUILD_DOCS=0 | ||
env: TOOLSET=g++-5 TOOLSET_C=gcc-5 BUILD_TYPE='Debug' BUILD_DOCS=0 | ||
- os: linux | ||
compiler: gcc | ||
addons: | ||
apt: | ||
sources: ['ubuntu-toolchain-r-test'] | ||
packages: ['g++-5'] | ||
env: TOOLSET=g++-5 BUILD_TYPE='Release' BUILD_DOCS=0 | ||
env: TOOLSET=g++-5 TOOLSET_C=gcc-5 BUILD_TYPE='Release' BUILD_DOCS=0 | ||
|
||
- os: osx | ||
compiler: clang | ||
env: TOOLSET=clang++ BUILD_TYPE='Debug' BUILD_DOCS=0 | ||
env: TOOLSET=clang++ TOOLSET_C=clang BUILD_TYPE='Debug' BUILD_DOCS=0 | ||
- os: osx | ||
compiler: clang | ||
env: TOOLSET=clang++ BUILD_TYPE='Release' BUILD_DOCS=0 | ||
env: TOOLSET=clang++ TOOLSET_C=clang BUILD_TYPE='Release' BUILD_DOCS=0 | ||
|
||
install: | ||
- cd ../ | ||
|
@@ -63,9 +63,13 @@ install: | |
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export CMAKE=$TRAVIS_BUILD_DIR/../cmake-3.3.0-Darwin-x86_64/CMake.app/Contents/bin/cmake; fi | ||
|
||
- export CXX=$TOOLSET | ||
- export CC=$TOOLSET_C | ||
- $CXX --version | ||
- $CC --version | ||
- $CMAKE --version | ||
|
||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pip install --user conan && export PATH=$PATH:$HOME/.local/bin; fi | ||
|
||
- cd type_safe/ | ||
|
||
script: | ||
|
@@ -74,6 +78,10 @@ script: | |
- $CMAKE --build . | ||
- ./test/type_safe_test | ||
|
||
# Run conan package test (only on linux, pip is not available in the osx build) | ||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then conan remote add Manu343726 https://api.bintray.com/conan/manu343726/conan-packages; fi | ||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cd .. && conan create . Manu343726/testing --build=outdated && cd build; fi | ||
|
||
after_success: | ||
- git config --global user.name "Travis CI" | ||
- git config --global user.email "[email protected]" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from conans import ConanFile | ||
from conans.tools import download, untargz | ||
import os | ||
|
||
class TypeSafe(ConanFile): | ||
name = 'type_safe' | ||
url = 'https://github.com/foonathan/type_safe' | ||
version = '0.1' | ||
requires = 'debug_assert/1.3@Manu343726/testing' | ||
exports = '*.hpp' | ||
generators = 'cmake' | ||
|
||
|
||
def source(self): | ||
tar = 'type_safe-{}.tar.gz'.format(self.version) | ||
url = 'https://github.com/foonathan/type_safe/archive/v{}.tar.gz'.format(self.version) | ||
download(url, tar) | ||
untargz(tar) | ||
|
||
def package(self): | ||
includedir = os.path.join('include', 'type_safe') | ||
srcdir = os.path.join('type_safe-{}'.format(self.version), includedir) | ||
self.copy('*.hpp', src=srcdir, dst=includedir) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
project(type_safe_test_package) | ||
cmake_minimum_required(VERSION 2.8) | ||
|
||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) | ||
conan_basic_setup(TARGETS) | ||
|
||
add_executable(example example.cpp) | ||
if(NOT MSVC) | ||
target_compile_options(example PRIVATE -std=c++11) | ||
endif() | ||
|
||
target_link_libraries(example PRIVATE ${CONAN_TARGETS}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from conans import ConanFile, CMake | ||
import os | ||
|
||
class TypeSafe(ConanFile): | ||
settings = 'os', 'compiler', 'build_type', 'arch' | ||
generators = 'cmake' | ||
|
||
def build(self): | ||
cmake = CMake(self) | ||
cmake.configure() | ||
cmake.build() | ||
|
||
def test(self): | ||
self.run(os.path.join('.', 'bin', 'example')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Copyright (C) 2016 Jonathan Müller <[email protected]> | ||
// This file is subject to the license terms in the LICENSE file | ||
// found in the top-level directory of this distribution. | ||
|
||
#include <cctype> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include <type_safe/optional.hpp> | ||
#include <type_safe/optional_ref.hpp> | ||
#include <type_safe/visitor.hpp> | ||
|
||
namespace ts = type_safe; | ||
|
||
// type safe back function | ||
// impossible to forget precondition | ||
ts::optional<char> back(const std::string& str) | ||
{ | ||
return str.empty() ? ts::nullopt : ts::make_optional(str.back()); | ||
} | ||
|
||
// some imaginary lookup function | ||
ts::optional<int> lookup(char c) | ||
{ | ||
// simulate lookup | ||
return c == 'T' ? ts::nullopt : ts::make_optional(c + 1); | ||
} | ||
|
||
// task: get last character of string, | ||
// convert it to upper case | ||
// look it up | ||
// and return the integer or 0 if there is no integer | ||
|
||
// this is how'd you do it with std::optional | ||
int task_std(const std::string& str) | ||
{ | ||
auto c = back(str); | ||
if (!c) | ||
return 0; | ||
auto upper_case = std::toupper(c.value()); | ||
auto result = lookup(upper_case); | ||
return result.value_or(0); | ||
} | ||
|
||
// this is how'd you do it with the monadic functionality | ||
// there is no need for branches and no errors possible | ||
// it generates identical assembler code | ||
int task_monadic(const std::string& str) | ||
{ | ||
return back(str) | ||
// map takes a functor and applies it to the stored value, if there is any | ||
// the result is another optional with possibly different type | ||
.map([](char c) -> char { return std::toupper(c); }) | ||
// lookup is similar to map | ||
// but the result of map(lookup) would be a ts::optional<ts::optional<int>> | ||
// bind() calls unwrap() to flatten it to ts::optional<int> | ||
.bind(lookup) | ||
// value_or() as usual | ||
.value_or(0); | ||
} | ||
|
||
// a visitor for an optional | ||
// this again makes branches unnecessary | ||
struct visitor | ||
{ | ||
template <typename T> | ||
void operator()(const T& val) | ||
{ | ||
std::cout << val << '\n'; | ||
} | ||
|
||
void operator()(ts::nullopt_t) | ||
{ | ||
std::cout << "nothing :(\n"; | ||
} | ||
}; | ||
|
||
int main() | ||
{ | ||
std::cout << task_std("Hello World") << ' ' << task_monadic("Hello World") << '\n'; | ||
std::cout << task_std("Hallo Welt") << ' ' << task_monadic("Hallo Welt") << '\n'; | ||
std::cout << task_std("") << ' ' << task_monadic("") << '\n'; | ||
|
||
// visit an optional | ||
ts::optional<int> opt(45); | ||
ts::visit(visitor{}, opt); | ||
opt.reset(); | ||
ts::visit(visitor{}, opt); | ||
|
||
// savely manipulate the value if there is one | ||
// with() is an inplace map() | ||
// and thus more efficient if you do not need to change the type | ||
ts::with(opt, [](int& i) { | ||
std::cout << "got: " << i << '\n'; | ||
++i; | ||
}); | ||
|
||
// an optional reference | ||
// basically a pointer, but provides the funcionality of optional | ||
ts::optional_ref<int> ref; | ||
|
||
int a = 42; | ||
ref = a; // assignment rebinds | ||
std::cout << ref.value() << '\n'; | ||
|
||
ref.value() = 0; | ||
std::cout << a << '\n'; | ||
|
||
int b = 5; | ||
ref.value_or(b)++; | ||
std::cout << a << ' ' << b << '\n'; | ||
|
||
ref = nullptr; // assign nullptr as additional way to reset | ||
|
||
// an optional reference to const | ||
ts::optional_ref<const int> ref_const(ref); | ||
|
||
// create optional_ref from pointer | ||
auto ptr = ts::ref(&a); | ||
auto ptr_const = ts::cref(&a); | ||
|
||
// map() takes a functor and wraps the result in an optional itself | ||
// transform() does not wrap it in an optional to allow arbitrary transformation | ||
// but it needs a fallback value if there is no value stored | ||
// here transform() is used to transform an optional_ref to a normal optional | ||
auto ptr_transformed = ptr.transform(ts::optional<int>(), [](int a) { return a; }); | ||
// note that the same for this particular situation can be achieved like this | ||
ptr_transformed = ts::copy(ptr); // there is also ts::move() to move the value | ||
std::cout << ptr_transformed.value() << '\n'; | ||
} |