-
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.
This commit adds a conan.io package recipe using my testing channel (Manu343726/testing). The package will be manually released into my own conan repository in artifactory (https://bintray.com/manu343726/conan-packages). Note debug_assert is released there too. The package is tagged with version 0.1, until an official release of type_safe is done. The package currently depends on debug_assert 1.3, the latest release packaged. No automatic conan packaging is implemented in the CI, only a package test. Note this must be trivial (encrypting the artifactory user key in travis, using one of the travis environment variables to check if we're building a release, etc).
- Loading branch information
1 parent
0320c2e
commit fa24512
Showing
7 changed files
with
188 additions
and
1 deletion.
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
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,25 @@ | ||
from conans import ConanFile | ||
from conans.tools import download, untargz | ||
import os | ||
|
||
class TypeSafe(ConanFile): | ||
name = 'type_safe' | ||
url = 'https://foonathan.github.io/blog/2016/10/11/type-safe.html' | ||
version = '0.1' | ||
username = 'Manu343726' | ||
channel = 'testing' | ||
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'; | ||
} |