feat use meta
This commit is contained in:
parent
0a6b13c218
commit
ed9e57c5e8
14
src/sled/error/error.h
Normal file
14
src/sled/error/error.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef SLED_ERROR_ERROR_H
|
||||||
|
#define SLED_ERROR_ERROR_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
class Error {
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
static Error Wrap();
|
||||||
|
};
|
||||||
|
}// namespace sled
|
||||||
|
|
||||||
|
#endif// SLED_ERROR_ERROR_H
|
@ -8,6 +8,7 @@
|
|||||||
#include "sled/futures/internal/promise.h"
|
#include "sled/futures/internal/promise.h"
|
||||||
#include "sled/lang/attributes.h"
|
#include "sled/lang/attributes.h"
|
||||||
#include "sled/log/log.h"
|
#include "sled/log/log.h"
|
||||||
|
#include "sled/meta/type_traits.h"
|
||||||
#include "sled/synchronization/event.h"
|
#include "sled/synchronization/event.h"
|
||||||
#include "sled/synchronization/mutex.h"
|
#include "sled/synchronization/mutex.h"
|
||||||
#include "sled/task_queue/task_queue_base.h"
|
#include "sled/task_queue/task_queue_base.h"
|
||||||
@ -17,16 +18,16 @@
|
|||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
namespace future_detail {
|
namespace future_detail {
|
||||||
template<typename F, typename... Args>
|
// template<typename F, typename... Args>
|
||||||
struct is_invocable : std::is_constructible<std::function<void(Args...)>,
|
// struct is_invocable : std::is_constructible<std::function<void(Args...)>,
|
||||||
std::reference_wrapper<typename std::remove_reference<F>::type>> {};
|
// std::reference_wrapper<typename std::remove_reference<F>::type>> {};
|
||||||
|
//
|
||||||
template<typename R, typename F, typename... Args>
|
// template<typename R, typename F, typename... Args>
|
||||||
struct is_invocable_r : std::is_constructible<std::function<R(Args...)>,
|
// struct is_invocable_r : std::is_constructible<std::function<R(Args...)>,
|
||||||
std::reference_wrapper<typename std::remove_reference<F>::type>> {};
|
// std::reference_wrapper<typename std::remove_reference<F>::type>> {};
|
||||||
|
//
|
||||||
template<bool cond, typename T = void>
|
// template<bool cond, typename T = void>
|
||||||
using enable_if_t = typename std::enable_if<cond, T>::type;
|
// using enable_if_t = typename std::enable_if<cond, T>::type;
|
||||||
|
|
||||||
enum FutureState {
|
enum FutureState {
|
||||||
kNotCompletedFuture = 0,
|
kNotCompletedFuture = 0,
|
||||||
@ -83,27 +84,27 @@ public:
|
|||||||
Future<T, FailureT> &operator=(Future<T, FailureT> &&) noexcept = default;
|
Future<T, FailureT> &operator=(Future<T, FailureT> &&) noexcept = default;
|
||||||
~Future() = default;
|
~Future() = default;
|
||||||
|
|
||||||
Future(const T &value) noexcept
|
// Future(const T &value) noexcept
|
||||||
{
|
// {
|
||||||
static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types");
|
// static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types");
|
||||||
data_ = Future<T, FailureT>::Create().data_;
|
// data_ = Future<T, FailureT>::Create().data_;
|
||||||
FillSuccess(value);
|
// FillSuccess(value);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Future(T &&value) noexcept
|
// Future(T &&value) noexcept
|
||||||
{
|
// {
|
||||||
static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types");
|
// static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types");
|
||||||
data_ = Future<T, FailureT>::Create().data_;
|
// data_ = Future<T, FailureT>::Create().data_;
|
||||||
FillSuccess(std::move(value));
|
// FillSuccess(std::move(value));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
template<typename = typename std::enable_if<!std::is_same<T, FailureT>::value>>
|
// template<typename = EnableIfT<!std::is_same<T, FailureT>::value>>
|
||||||
Future(const FailureT &failure) noexcept
|
// Future(const FailureT &failure) noexcept
|
||||||
{
|
// {
|
||||||
static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types");
|
// static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types");
|
||||||
data_ = Future<T, FailureT>::Create().data_;
|
// data_ = Future<T, FailureT>::Create().data_;
|
||||||
FillFailure(failure);
|
// FillFailure(failure);
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool operator==(const Future<T, FailureT> &other) const noexcept { return data_ == other.data_; }
|
bool operator==(const Future<T, FailureT> &other) const noexcept { return data_ == other.data_; }
|
||||||
|
|
||||||
@ -147,8 +148,7 @@ public:
|
|||||||
return IsCompleted();
|
return IsCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dummy = void,
|
template<typename Dummy = void, typename = EnableIfT<std::is_copy_constructible<T>::value, Dummy>>
|
||||||
typename = typename std::enable_if<std::is_copy_constructible<T>::value, Dummy>::type>
|
|
||||||
T Result() const noexcept
|
T Result() const noexcept
|
||||||
{
|
{
|
||||||
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
||||||
@ -183,7 +183,7 @@ public:
|
|||||||
return FailureT();
|
return FailureT();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename = typename std::enable_if<future_detail::is_invocable<Func, T>::value>::type>
|
template<typename Func, typename = EnableIfT<IsInvocable<Func, T>::value>>
|
||||||
Future<T, FailureT> OnSuccess(Func &&f) const noexcept
|
Future<T, FailureT> OnSuccess(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
||||||
@ -211,7 +211,7 @@ public:
|
|||||||
return Future<T, FailureT>(data_);
|
return Future<T, FailureT>(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func, FailureT>::value>>
|
template<typename Func, typename = EnableIfT<IsInvocable<Func, FailureT>::value>>
|
||||||
Future<T, FailureT> OnFailure(Func &&f) const noexcept
|
Future<T, FailureT> OnFailure(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
||||||
@ -239,7 +239,7 @@ public:
|
|||||||
return Future<T, FailureT>(data_);
|
return Future<T, FailureT>(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>>
|
template<typename Func, typename = EnableIfT<IsInvocable<Func>::value>>
|
||||||
Future<T, FailureT> OnComplete(Func &&f) const noexcept
|
Future<T, FailureT> OnComplete(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
SLED_ASSERT(data_ != nullptr, "Future is not valid");
|
||||||
@ -248,7 +248,7 @@ public:
|
|||||||
return Future<T, FailureT>(data_);
|
return Future<T, FailureT>(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable_r<bool, Func, T>::value>>
|
template<typename Func, typename = EnableIfT<IsInvocableR<bool, Func, T>::value>>
|
||||||
Future<T, FailureT>
|
Future<T, FailureT>
|
||||||
Filter(Func &&f,
|
Filter(Func &&f,
|
||||||
const FailureT &rejected = failure::FailureFromString<FailureT>("Result wasn't good enough")) const noexcept
|
const FailureT &rejected = failure::FailureFromString<FailureT>("Result wasn't good enough")) const noexcept
|
||||||
@ -271,7 +271,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename U = eggs::invoke_result_t<Func, T>>
|
template<typename Func, typename U = InvokeResultT<Func, T>>
|
||||||
Future<U, FailureT> Map(Func &&f) const noexcept
|
Future<U, FailureT> Map(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
Future<U, FailureT> result = Future<U, FailureT>::Create();
|
Future<U, FailureT> result = Future<U, FailureT>::Create();
|
||||||
@ -288,7 +288,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename OtherFailureT = eggs::invoke_result_t<Func, FailureT>>
|
template<typename Func, typename OtherFailureT = InvokeResultT<Func, FailureT>>
|
||||||
Future<T, OtherFailureT> MapFailure(Func &&f) const noexcept
|
Future<T, OtherFailureT> MapFailure(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
Future<T, OtherFailureT> result = Future<T, OtherFailureT>::Create();
|
Future<T, OtherFailureT> result = Future<T, OtherFailureT>::Create();
|
||||||
@ -305,7 +305,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>>().Result())>
|
template<typename Func, typename U = decltype(std::declval<InvokeResultT<Func, T>>().Result())>
|
||||||
Future<U, FailureT> FlatMap(Func &&f) const noexcept
|
Future<U, FailureT> FlatMap(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
Future<U, FailureT> result = Future<U, FailureT>::Create();
|
Future<U, FailureT> result = Future<U, FailureT>::Create();
|
||||||
@ -324,7 +324,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>().Result()>)>
|
template<typename Func, typename U = decltype(std::declval<InvokeResultT<Func, T>().Result()>)>
|
||||||
Future<U, FailureT> AndThen(Func &&f) const noexcept
|
Future<U, FailureT> AndThen(Func &&f) const noexcept
|
||||||
{
|
{
|
||||||
return FlatMap([f](const T &) { return f(); });
|
return FlatMap([f](const T &) { return f(); });
|
||||||
@ -353,7 +353,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>>
|
template<typename Func, typename = EnableIfT<IsInvocable<Func>::value>>
|
||||||
static Future<T, FailureT> Async(Func &&f) noexcept
|
static Future<T, FailureT> Async(Func &&f) noexcept
|
||||||
{
|
{
|
||||||
Future<T, FailureT> result = Future<T, FailureT>::Create();
|
Future<T, FailureT> result = Future<T, FailureT>::Create();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <sled/futures/future.h>
|
#include <sled/futures/future.h>
|
||||||
#include <sled/system/thread.h>
|
#include <sled/system/thread.h>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
TEST_SUITE("future")
|
TEST_SUITE("future")
|
||||||
{
|
{
|
||||||
@ -122,8 +121,8 @@ TEST_SUITE("future")
|
|||||||
|
|
||||||
TEST_CASE("Constructor")
|
TEST_CASE("Constructor")
|
||||||
{
|
{
|
||||||
sled::Future<int, std::string> f1 = 1;
|
auto f1 = sled::Future<int, std::string>::Successful(1);
|
||||||
sled::Future<int, std::string> f2 = std::string("1");
|
auto f2 = sled::Future<int, std::string>::Failed(std::string("1"));
|
||||||
REQUIRE(f1.IsCompleted());
|
REQUIRE(f1.IsCompleted());
|
||||||
REQUIRE(f2.IsFailed());
|
REQUIRE(f2.IsFailed());
|
||||||
REQUIRE_EQ(f1.Result(), 1);
|
REQUIRE_EQ(f1.Result(), 1);
|
||||||
@ -132,14 +131,14 @@ TEST_SUITE("future")
|
|||||||
|
|
||||||
TEST_CASE("MapFailure")
|
TEST_CASE("MapFailure")
|
||||||
{
|
{
|
||||||
sled::Future<int, bool> f = false;
|
auto f = sled::Future<int, bool>::Failed(false);
|
||||||
auto f1 = f.MapFailure([](bool) { return std::string("error"); });
|
auto f1 = f.MapFailure([](bool) { return std::string("error"); });
|
||||||
CHECK_EQ(f1.FailureReason(), "error");
|
CHECK_EQ(f1.FailureReason(), "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Chain")
|
TEST_CASE("Chain")
|
||||||
{
|
{
|
||||||
sled::Future<int, bool> f = 1;
|
auto f = sled::Future<int, bool>::Successful(1);
|
||||||
auto f1 = f.Map([](int i) { return i + 1; })
|
auto f1 = f.Map([](int i) { return i + 1; })
|
||||||
.FlatMap([](int i) {
|
.FlatMap([](int i) {
|
||||||
sled::Promise<std::string, bool> p;
|
sled::Promise<std::string, bool> p;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "sled/any.h"
|
#include "sled/any.h"
|
||||||
#include "sled/nonstd/string_view.h"
|
#include "sled/meta/type_traits.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
@ -25,16 +25,14 @@ private:
|
|||||||
std::string message_;
|
std::string message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename FailureT,
|
template<typename FailureT, typename = EnableIfT<!std::is_constructible<FailureT, std::string>::value>>
|
||||||
typename = typename std::enable_if<!std::is_constructible<FailureT, std::string>::value>::type>
|
|
||||||
inline FailureT
|
inline FailureT
|
||||||
FailureFromString(std::string &&str)
|
FailureFromString(std::string &&str)
|
||||||
{
|
{
|
||||||
return FailureT();
|
return FailureT();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FailureT,
|
template<typename FailureT, typename = EnableIfT<std::is_constructible<FailureT, const std::string &>::value>>
|
||||||
typename = typename std::enable_if<std::is_constructible<FailureT, const std::string &>::value>::type>
|
|
||||||
inline FailureT
|
inline FailureT
|
||||||
FailureFromString(const std::string &str)
|
FailureFromString(const std::string &str)
|
||||||
{
|
{
|
||||||
|
34
src/sled/meta/type_traits.h
Normal file
34
src/sled/meta/type_traits.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef SLED_META_TYPE_TRAITS_H
|
||||||
|
#define SLED_META_TYPE_TRAITS_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sled/exec/detail/invoke_result.h"
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
template<typename Callable, typename... Args>
|
||||||
|
using InvokeResultT = typename eggs::invoke_result_t<Callable, Args...>;
|
||||||
|
|
||||||
|
template<typename Callable, typename... Args>
|
||||||
|
using IsInvocable = eggs::is_invocable<Callable, Args...>;
|
||||||
|
|
||||||
|
template<typename Convertible, typename Callable, typename... Args>
|
||||||
|
using IsInvocableR = eggs::is_invocable_r<Convertible, Callable, Args...>;
|
||||||
|
|
||||||
|
template<typename Convertible, typename Callable, typename... Args>
|
||||||
|
using IsNothrowInvocable = eggs::is_nothrow_invocable<Convertible, Callable, Args...>;
|
||||||
|
|
||||||
|
template<typename Convertible, typename Callable, typename... Args>
|
||||||
|
using IsNothrowInvocableR = eggs::is_nothrow_invocable_r<Convertible, Callable, Args...>;
|
||||||
|
|
||||||
|
// EnableIfT
|
||||||
|
template<bool B, typename T = void>
|
||||||
|
using EnableIfT = typename std::enable_if<B, T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using DecayT = typename std::decay<T>::type;
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
|
||||||
|
#endif// SLED_META_TYPE_TRAITS_H
|
Loading…
Reference in New Issue
Block a user