move return_type_of_t from result to traits

This commit is contained in:
ToruNiina
2019-02-13 13:34:03 +09:00
parent 8c3854b28b
commit 32dcc35918
2 changed files with 46 additions and 32 deletions

View File

@@ -2,6 +2,7 @@
// Distributed under the MIT License. // Distributed under the MIT License.
#ifndef TOML11_RESULT_H #ifndef TOML11_RESULT_H
#define TOML11_RESULT_H #define TOML11_RESULT_H
#include "traits.hpp"
#include <type_traits> #include <type_traits>
#include <stdexcept> #include <stdexcept>
#include <utility> #include <utility>
@@ -13,19 +14,6 @@
namespace toml 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> template<typename T>
struct success struct success
{ {
@@ -441,21 +429,21 @@ struct result
// F: T -> U // F: T -> U
// retval: result<U, E> // retval: result<U, E>
template<typename F> template<typename F>
result<return_type_of_t<F, value_type&>, error_type> result<detail::return_type_of_t<F, value_type&>, error_type>
map(F&& f) & map(F&& f) &
{ {
if(this->is_ok()){return ok(f(this->as_ok()));} if(this->is_ok()){return ok(f(this->as_ok()));}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
result<return_type_of_t<F, value_type const&>, error_type> result<detail::return_type_of_t<F, value_type const&>, error_type>
map(F&& f) const& map(F&& f) const&
{ {
if(this->is_ok()){return ok(f(this->as_ok()));} if(this->is_ok()){return ok(f(this->as_ok()));}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
result<return_type_of_t<F, value_type &&>, error_type> result<detail::return_type_of_t<F, value_type &&>, error_type>
map(F&& f) && map(F&& f) &&
{ {
if(this->is_ok()){return ok(f(std::move(this->as_ok())));} if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
@@ -466,21 +454,21 @@ struct result
// F: E -> F // F: E -> F
// retval: result<T, F> // retval: result<T, F>
template<typename F> template<typename F>
result<value_type, return_type_of_t<F, error_type&>> result<value_type, detail::return_type_of_t<F, error_type&>>
map_err(F&& f) & map_err(F&& f) &
{ {
if(this->is_err()){return err(f(this->as_err()));} if(this->is_err()){return err(f(this->as_err()));}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
result<value_type, return_type_of_t<F, error_type const&>> result<value_type, detail::return_type_of_t<F, error_type const&>>
map_err(F&& f) const& map_err(F&& f) const&
{ {
if(this->is_err()){return err(f(this->as_err()));} if(this->is_err()){return err(f(this->as_err()));}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
result<value_type, return_type_of_t<F, error_type&&>> result<value_type, detail::return_type_of_t<F, error_type&&>>
map_err(F&& f) && map_err(F&& f) &&
{ {
if(this->is_err()){return err(f(std::move(this->as_err())));} if(this->is_err()){return err(f(std::move(this->as_err())));}
@@ -491,21 +479,21 @@ struct result
// F: T -> U // F: T -> U
// retval: U // retval: U
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, value_type&> detail::return_type_of_t<F, value_type&>
map_or_else(F&& f, U&& opt) & map_or_else(F&& f, U&& opt) &
{ {
if(this->is_err()){return std::forward<U>(opt);} if(this->is_err()){return std::forward<U>(opt);}
return f(this->as_ok()); return f(this->as_ok());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, value_type const&> detail::return_type_of_t<F, value_type const&>
map_or_else(F&& f, U&& opt) const& map_or_else(F&& f, U&& opt) const&
{ {
if(this->is_err()){return std::forward<U>(opt);} if(this->is_err()){return std::forward<U>(opt);}
return f(this->as_ok()); return f(this->as_ok());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, value_type&&> detail::return_type_of_t<F, value_type&&>
map_or_else(F&& f, U&& opt) && map_or_else(F&& f, U&& opt) &&
{ {
if(this->is_err()){return std::forward<U>(opt);} if(this->is_err()){return std::forward<U>(opt);}
@@ -516,21 +504,21 @@ struct result
// F: E -> U // F: E -> U
// retval: U // retval: U
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, error_type&> detail::return_type_of_t<F, error_type&>
map_err_or_else(F&& f, U&& opt) & map_err_or_else(F&& f, U&& opt) &
{ {
if(this->is_ok()){return std::forward<U>(opt);} if(this->is_ok()){return std::forward<U>(opt);}
return f(this->as_err()); return f(this->as_err());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, error_type const&> detail::return_type_of_t<F, error_type const&>
map_err_or_else(F&& f, U&& opt) const& map_err_or_else(F&& f, U&& opt) const&
{ {
if(this->is_ok()){return std::forward<U>(opt);} if(this->is_ok()){return std::forward<U>(opt);}
return f(this->as_err()); return f(this->as_err());
} }
template<typename F, typename U> template<typename F, typename U>
return_type_of_t<F, error_type&&> detail::return_type_of_t<F, error_type&&>
map_err_or_else(F&& f, U&& opt) && map_err_or_else(F&& f, U&& opt) &&
{ {
if(this->is_ok()){return std::forward<U>(opt);} if(this->is_ok()){return std::forward<U>(opt);}
@@ -542,21 +530,21 @@ struct result
// toml::err(error_type) should be convertible to U. // toml::err(error_type) should be convertible to U.
// normally, type U is another result<S, F> and E is convertible to F // normally, type U is another result<S, F> and E is convertible to F
template<typename F> template<typename F>
return_type_of_t<F, value_type&> detail::return_type_of_t<F, value_type&>
and_then(F&& f) & and_then(F&& f) &
{ {
if(this->is_ok()){return f(this->as_ok());} if(this->is_ok()){return f(this->as_ok());}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
return_type_of_t<F, value_type const&> detail::return_type_of_t<F, value_type const&>
and_then(F&& f) const& and_then(F&& f) const&
{ {
if(this->is_ok()){return f(this->as_ok());} if(this->is_ok()){return f(this->as_ok());}
return err(this->as_err()); return err(this->as_err());
} }
template<typename F> template<typename F>
return_type_of_t<F, value_type&&> detail::return_type_of_t<F, value_type&&>
and_then(F&& f) && and_then(F&& f) &&
{ {
if(this->is_ok()){return f(std::move(this->as_ok()));} if(this->is_ok()){return f(std::move(this->as_ok()));}
@@ -568,21 +556,21 @@ struct result
// toml::ok(value_type) should be convertible to U. // toml::ok(value_type) should be convertible to U.
// normally, type U is another result<S, F> and T is convertible to S // normally, type U is another result<S, F> and T is convertible to S
template<typename F> template<typename F>
return_type_of_t<F, error_type&> detail::return_type_of_t<F, error_type&>
or_else(F&& f) & or_else(F&& f) &
{ {
if(this->is_err()){return f(this->as_err());} if(this->is_err()){return f(this->as_err());}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
return_type_of_t<F, error_type const&> detail::return_type_of_t<F, error_type const&>
or_else(F&& f) const& or_else(F&& f) const&
{ {
if(this->is_err()){return f(this->as_err());} if(this->is_err()){return f(this->as_err());}
return ok(this->as_ok()); return ok(this->as_ok());
} }
template<typename F> template<typename F>
return_type_of_t<F, error_type&&> detail::return_type_of_t<F, error_type&&>
or_else(F&& f) && or_else(F&& f) &&
{ {
if(this->is_err()){return f(std::move(this->as_err()));} if(this->is_err()){return f(std::move(this->as_err()));}

View File

@@ -15,6 +15,9 @@ namespace detail
template<typename T> template<typename T>
using unwrap_t = typename std::decay<T>::type; using unwrap_t = typename std::decay<T>::type;
// ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class
struct has_iterator_impl struct has_iterator_impl
{ {
template<typename T> static std::true_type check(typename T::iterator*); template<typename T> static std::true_type check(typename T::iterator*);
@@ -63,6 +66,9 @@ struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){}
#undef decltype(...) #undef decltype(...)
#endif #endif
// ---------------------------------------------------------------------------
// C++17 and/or/not
template<typename ...> struct conjunction : std::true_type{}; template<typename ...> struct conjunction : std::true_type{};
template<typename T> struct conjunction<T> : T{}; template<typename T> struct conjunction<T> : T{};
template<typename T, typename ... Ts> template<typename T, typename ... Ts>
@@ -80,6 +86,9 @@ struct disjunction<T, Ts...> :
template<typename T> template<typename T>
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{}; struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
// ---------------------------------------------------------------------------
// normal type checker
template<typename T> struct is_std_pair : std::false_type{}; template<typename T> struct is_std_pair : std::false_type{};
template<typename T1, typename T2> template<typename T1, typename T2>
struct is_std_pair<std::pair<T1, T2>> : std::true_type{}; struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
@@ -92,7 +101,9 @@ template<typename T> struct is_chrono_duration: std::false_type{};
template<typename Rep, typename Period> template<typename Rep, typename Period>
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{}; struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
// to use toml::get<std::tuple<T1, T2, ...>> in C++11 // ---------------------------------------------------------------------------
// C++14 index_sequence
template<std::size_t ... Ns> struct index_sequence{}; template<std::size_t ... Ns> struct index_sequence{};
template<typename IS, std::size_t N> struct push_back_index_sequence{}; template<typename IS, std::size_t N> struct push_back_index_sequence{};
@@ -116,6 +127,21 @@ struct index_sequence_maker<0>
template<std::size_t N> template<std::size_t N>
using make_index_sequence = typename index_sequence_maker<N-1>::type; using make_index_sequence = typename index_sequence_maker<N-1>::type;
// ---------------------------------------------------------------------------
// return_type_of_t
#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
}// detail }// detail
}//toml }//toml
#endif // TOML_TRAITS #endif // TOML_TRAITS