mirror of
https://github.com/ToruNiina/toml11.git
synced 2024-11-12 15:50:07 +00:00
Merge branch 'result' into combinator
- fix some of the constructors of result - add some utility member functions to boost
This commit is contained in:
commit
f8aa604959
@ -109,3 +109,260 @@ BOOST_AUTO_TEST_CASE(test_assignment)
|
||||
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_map)
|
||||
{
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::ok(42));
|
||||
const auto mapped = result.map(
|
||||
[](const int i) -> int {
|
||||
return i * 2;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2);
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||
const auto mapped = std::move(result).map(
|
||||
[](std::unique_ptr<int> i) -> int {
|
||||
return *i;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||
}
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = result.map(
|
||||
[](const int i) -> int {
|
||||
return i * 2;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = std::move(result).map(
|
||||
[](std::unique_ptr<int> i) -> int {
|
||||
return *i;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_map_err)
|
||||
{
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::ok(42));
|
||||
const auto mapped = result.map_err(
|
||||
[](const std::string s) -> std::string {
|
||||
return s + s;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||
const auto mapped = std::move(result).map_err(
|
||||
[](const std::string s) -> std::string {
|
||||
return s + s;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(*(mapped.unwrap()), 42);
|
||||
}
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = result.map_err(
|
||||
[](const std::string s) -> std::string {
|
||||
return s + s;
|
||||
});
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
|
||||
}
|
||||
{
|
||||
toml::result<int, std::unique_ptr<std::string>>
|
||||
result(toml::err(std::unique_ptr<std::string>(new std::string("hoge"))));
|
||||
const auto mapped = std::move(result).map_err(
|
||||
[](std::unique_ptr<std::string> p) -> std::string {
|
||||
return *p;
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_map_or_else)
|
||||
{
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::ok(42));
|
||||
const auto mapped = result.map_or_else(
|
||||
[](const int i) -> int {
|
||||
return i * 2;
|
||||
}, 54);
|
||||
|
||||
BOOST_CHECK_EQUAL(mapped, 42 * 2);
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||
const auto mapped = std::move(result).map_or_else(
|
||||
[](std::unique_ptr<int> i) -> int {
|
||||
return *i;
|
||||
}, 54);
|
||||
|
||||
BOOST_CHECK_EQUAL(mapped, 42);
|
||||
}
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = result.map_or_else(
|
||||
[](const int i) -> int {
|
||||
return i * 2;
|
||||
}, 54);
|
||||
|
||||
BOOST_CHECK_EQUAL(mapped, 54);
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = std::move(result).map_or_else(
|
||||
[](std::unique_ptr<int> i) -> int {
|
||||
return *i;
|
||||
}, 54);
|
||||
|
||||
BOOST_CHECK_EQUAL(mapped, 54);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_and_then)
|
||||
{
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::ok(42));
|
||||
const auto mapped = result.and_then(
|
||||
[](const int i) -> toml::result<int, std::string> {
|
||||
return toml::ok(i * 2);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2);
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||
const auto mapped = std::move(result).and_then(
|
||||
[](std::unique_ptr<int> i) -> toml::result<int, std::string> {
|
||||
return toml::ok(*i);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||
}
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = result.and_then(
|
||||
[](const int i) -> toml::result<int, std::string> {
|
||||
return toml::ok(i * 2);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = std::move(result).and_then(
|
||||
[](std::unique_ptr<int> i) -> toml::result<int, std::string> {
|
||||
return toml::ok(*i);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_or_else)
|
||||
{
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::ok(42));
|
||||
const auto mapped = result.or_else(
|
||||
[](const std::string& s) -> toml::result<int, std::string> {
|
||||
return toml::err(s + s);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||
const auto mapped = std::move(result).or_else(
|
||||
[](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
|
||||
return toml::err(s + s);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!!mapped);
|
||||
BOOST_CHECK(mapped.is_ok());
|
||||
BOOST_CHECK(!mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(*mapped.unwrap(), 42);
|
||||
}
|
||||
{
|
||||
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = result.or_else(
|
||||
[](const std::string& s) -> toml::result<int, std::string> {
|
||||
return toml::err(s + s);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
|
||||
}
|
||||
{
|
||||
toml::result<std::unique_ptr<int>, std::string>
|
||||
result(toml::err<std::string>("hoge"));
|
||||
const auto mapped = std::move(result).or_else(
|
||||
[](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
|
||||
return toml::err(s + s);
|
||||
});
|
||||
|
||||
BOOST_CHECK(!mapped);
|
||||
BOOST_CHECK(!mapped.is_ok());
|
||||
BOOST_CHECK(mapped.is_err());
|
||||
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
|
||||
}
|
||||
}
|
||||
|
163
toml/result.hpp
163
toml/result.hpp
@ -8,6 +8,19 @@
|
||||
namespace toml
|
||||
{
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
template<typename F, typename ... Args>
|
||||
using return_type_of_t = std::invoke_result_t<F, Args...>;
|
||||
|
||||
#else
|
||||
// result_of is deprecated after C++17
|
||||
template<typename F, typename ... Args>
|
||||
using return_type_of_t = typename std::result_of<F(Args...)>::type;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct success
|
||||
{
|
||||
@ -238,12 +251,12 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
}
|
||||
}
|
||||
@ -267,12 +280,12 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
}
|
||||
}
|
||||
@ -390,6 +403,142 @@ struct result
|
||||
error_type const& as_err() const& noexcept {return this->fail.value;}
|
||||
error_type&& as_err() && noexcept {return std::move(this->fail.value);}
|
||||
|
||||
|
||||
// prerequisities
|
||||
// F: T -> U
|
||||
// retval: result<U, E>
|
||||
template<typename F>
|
||||
result<return_type_of_t<F, value_type&>, error_type>
|
||||
map(F&& f) &
|
||||
{
|
||||
if(this->is_ok()){return ok(f(this->as_ok()));}
|
||||
return err(this->as_err());
|
||||
}
|
||||
template<typename F>
|
||||
result<return_type_of_t<F, value_type const&>, error_type>
|
||||
map(F&& f) const&
|
||||
{
|
||||
if(this->is_ok()){return ok(f(this->as_ok()));}
|
||||
return err(this->as_err());
|
||||
}
|
||||
template<typename F>
|
||||
result<return_type_of_t<F, value_type &&>, error_type>
|
||||
map(F&& f) &&
|
||||
{
|
||||
if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
|
||||
return err(std::move(this->as_err()));
|
||||
}
|
||||
|
||||
// prerequisities
|
||||
// F: E -> F
|
||||
// retval: result<T, F>
|
||||
template<typename F>
|
||||
result<value_type, return_type_of_t<F, error_type&>>
|
||||
map_err(F&& f) &
|
||||
{
|
||||
if(this->is_err()){return err(f(this->as_err()));}
|
||||
return ok(this->as_ok());
|
||||
}
|
||||
template<typename F>
|
||||
result<value_type, return_type_of_t<F, error_type const&>>
|
||||
map_err(F&& f) const&
|
||||
{
|
||||
if(this->is_err()){return err(f(this->as_err()));}
|
||||
return ok(this->as_ok());
|
||||
}
|
||||
template<typename F>
|
||||
result<value_type, return_type_of_t<F, error_type&&>>
|
||||
map_err(F&& f) &&
|
||||
{
|
||||
if(this->is_err()){return err(f(std::move(this->as_err())));}
|
||||
return ok(std::move(this->as_ok()));
|
||||
}
|
||||
|
||||
// prerequisities
|
||||
// F: T -> U
|
||||
// retval: U
|
||||
template<typename F, typename U>
|
||||
return_type_of_t<F, value_type&>
|
||||
map_or_else(F&& f, U&& opt) &
|
||||
{
|
||||
if(this->is_err()){return std::forward<U>(opt);}
|
||||
return f(this->as_ok());
|
||||
}
|
||||
template<typename F, typename U>
|
||||
return_type_of_t<F, value_type const&>
|
||||
map_or_else(F&& f, U&& opt) const&
|
||||
{
|
||||
if(this->is_err()){return std::forward<U>(opt);}
|
||||
return f(this->as_ok());
|
||||
}
|
||||
template<typename F, typename U>
|
||||
return_type_of_t<F, value_type&&>
|
||||
map_or_else(F&& f, U&& opt) &&
|
||||
{
|
||||
if(this->is_err()){return std::forward<U>(opt);}
|
||||
return f(std::move(this->as_ok()));
|
||||
}
|
||||
|
||||
// prerequisities:
|
||||
// F: func T -> U
|
||||
// toml::err(error_type) should be convertible to U.
|
||||
// normally, type U is another result<S, F> and E is convertible to F
|
||||
template<typename F>
|
||||
return_type_of_t<F, value_type&>
|
||||
and_then(F&& f) &
|
||||
{
|
||||
if(this->is_ok()){return f(this->as_ok());}
|
||||
return err(this->as_err());
|
||||
}
|
||||
template<typename F>
|
||||
return_type_of_t<F, value_type const&>
|
||||
and_then(F&& f) const&
|
||||
{
|
||||
if(this->is_ok()){return f(this->as_ok());}
|
||||
return err(this->as_err());
|
||||
}
|
||||
template<typename F>
|
||||
return_type_of_t<F, value_type&&>
|
||||
and_then(F&& f) &&
|
||||
{
|
||||
if(this->is_ok()){return f(std::move(this->as_ok()));}
|
||||
return err(std::move(this->as_err()));
|
||||
}
|
||||
|
||||
// prerequisities:
|
||||
// F: func E -> U
|
||||
// toml::ok(value_type) should be convertible to U.
|
||||
// normally, type U is another result<S, F> and T is convertible to S
|
||||
template<typename F>
|
||||
return_type_of_t<F, error_type&>
|
||||
or_else(F&& f) &
|
||||
{
|
||||
if(this->is_err()){return f(this->as_err());}
|
||||
return ok(this->as_ok());
|
||||
}
|
||||
template<typename F>
|
||||
return_type_of_t<F, error_type const&>
|
||||
or_else(F&& f) const&
|
||||
{
|
||||
if(this->is_err()){return f(this->as_err());}
|
||||
return ok(this->as_ok());
|
||||
}
|
||||
template<typename F>
|
||||
return_type_of_t<F, error_type&&>
|
||||
or_else(F&& f) &&
|
||||
{
|
||||
if(this->is_err()){return f(std::move(this->as_err()));}
|
||||
return ok(std::move(this->as_ok()));
|
||||
}
|
||||
|
||||
void swap(result<T, E>& other)
|
||||
{
|
||||
result<T, E> tmp(std::move(*this));
|
||||
*this = std::move(other);
|
||||
other = std::move(tmp);
|
||||
return ;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void cleanup() noexcept
|
||||
@ -409,6 +558,12 @@ struct result
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, typename E>
|
||||
void swap(result<T, E>& lhs, result<T, E>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
return;
|
||||
}
|
||||
|
||||
} // toml11
|
||||
#endif// TOML11_RESULT_H
|
||||
|
Loading…
Reference in New Issue
Block a user