Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 3 additions & 29 deletions src/rpp/rpp/observables/fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <rpp/subjects/fwd.hpp>

#include <rpp/utils/constraints.hpp>
#include <rpp/utils/utils.hpp>

namespace rpp::constraint
{
Expand Down Expand Up @@ -52,24 +53,10 @@ template<constraint::decayed_type KeyType, constraint::decayed_type Type, constr
class grouped_observable;
}

namespace rpp::utils::details
{
template<typename TObservable>
struct is_observable_t
{
template<typename T, typename Strategy>
constexpr static std::true_type deduce(const rpp::observable<T, Strategy>*);
constexpr static std::false_type deduce(...);

using type = decltype(deduce(std::declval<std::decay_t<TObservable>*>()));
};

} // namespace rpp::utils::details

namespace rpp::constraint
{
template<typename T>
concept observable = rpp::utils::details::is_observable_t<std::decay_t<T>>::type::value;
concept observable = rpp::utils::is_base_of_v<T, rpp::observable>;
}

namespace rpp
Expand All @@ -80,21 +67,8 @@ class connectable_observable;

namespace rpp::utils
{
namespace details
{
template<rpp::constraint::observable TObservable>
struct extract_observable_type
{
template<typename T, typename Strategy>
constexpr static T deduce(const rpp::observable<T, Strategy>&);

using type = decltype(deduce(std::declval<std::decay_t<TObservable>>()));
};

} // namespace details

template<typename T>
using extract_observable_type_t = typename details::extract_observable_type<std::decay_t<T>>::type;
using extract_observable_type_t = typename rpp::utils::extract_base_type_params_t<T, rpp::observable>::template type_at_index_t<0>;
} // namespace rpp::utils

namespace rpp::constraint
Expand Down
20 changes: 3 additions & 17 deletions src/rpp/rpp/observers/fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <rpp/utils/constraints.hpp>
#include <rpp/utils/function_traits.hpp>
#include <rpp/utils/functors.hpp>
#include <rpp/utils/utils.hpp>

#include <exception>

Expand Down Expand Up @@ -231,29 +232,14 @@ using fake_observer = rpp::observer<T, fake_strategy>;

namespace rpp::utils
{
namespace details
{
template<typename T>
struct extract_observer_type : std::false_type
{
};

template<typename TT, typename Strategy>
struct extract_observer_type<rpp::observer<TT, Strategy>> : std::true_type
{
using type = TT;
};

} // namespace details

template<typename T>
using extract_observer_type_t = typename details::extract_observer_type<T>::type;
using extract_observer_type_t = typename rpp::utils::extract_base_type_params_t<T, rpp::observer>::template type_at_index_t<0>;
} // namespace rpp::utils

namespace rpp::constraint
{
template<typename T>
concept observer = rpp::utils::details::extract_observer_type<std::decay_t<T>>::value;
concept observer = rpp::utils::is_base_of_v<T, rpp::observer>;

template<typename T, typename Type>
concept observer_of_type = observer<std::decay_t<T>> && std::same_as<rpp::utils::extract_observer_type_t<std::decay_t<T>>, Type>;
Expand Down
43 changes: 6 additions & 37 deletions src/rpp/rpp/subjects/fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include <rpp/utils/constraints.hpp>

#include <rpp/utils/utils.hpp>

namespace rpp::subjects::details
{
namespace constraint
Expand All @@ -38,54 +40,21 @@ class serialized_strategy;

namespace rpp::subjects
{
/**
* @brief Subject which just multicasts values to observers subscribed on it. It contains two parts: observer and observable at the same time.
*
* @details Each observer obtains only values which emitted after corresponding subscribe. on_error/on_completer/unsubscribe cached and provided to new observers if any
*
* @warning this subject is not synchronized/serialized! It means, that expected to call callbacks of observer in the serialized way to follow observable contract: "Observables must issue notifications to observers serially (not in parallel).". If you are not sure or need extra serialization, please, use serialized_subject.
*
* @tparam Type value provided by this subject
*
* @ingroup subjects
* @see https://reactivex.io/documentation/subject.html
*/
template<rpp::constraint::decayed_type Type>
using publish_subject = details::base_subject<Type, details::publish_strategy<Type>>;
class publish_subject;

/**
* @brief Same as rpp::subjects::publish_subject, but on_next/on_error/on_completed calls are serialized via mutex
*
* @ingroup subjects
* @see https://reactivex.io/documentation/subject.html
*/
template<rpp::constraint::decayed_type Type>
using serialized_subject = details::base_subject<Type, details::serialized_strategy<Type>>;
class serialized_subject;
}

namespace rpp::subjects::utils
{
namespace details
{
template<typename T>
struct extract_subject_type : std::false_type
{
};

template<typename TT, typename Strategy>
struct extract_subject_type<rpp::subjects::details::base_subject<TT, Strategy>> : std::true_type
{
using type = TT;
};

} // namespace details

template<typename T>
using extract_subject_type_t = typename details::extract_subject_type<std::decay_t<T>>::type;
using extract_subject_type_t = typename rpp::utils::extract_base_type_params_t<T, rpp::subjects::details::base_subject>::template type_at_index_t<0>;
} // namespace rpp::utils

namespace rpp::constraint
{
template<typename T>
concept subject = rpp::subjects::utils::details::extract_subject_type<std::decay_t<T>>::value;
concept subject = rpp::utils::is_base_of_v<T, rpp::subjects::details::base_subject>;
}
24 changes: 23 additions & 1 deletion src/rpp/rpp/subjects/publish_subject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,26 @@ class publish_strategy
private:
std::shared_ptr<subject_state<Type>> m_state = std::make_shared<subject_state<Type>>();
};
} // namespace rpp::subjects::details
} // namespace rpp::subjects::details

namespace rpp::subjects
{
/**
* @brief Subject which just multicasts values to observers subscribed on it. It contains two parts: observer and observable at the same time.
*
* @details Each observer obtains only values which emitted after corresponding subscribe. on_error/on_completer/unsubscribe cached and provided to new observers if any
*
* @warning this subject is not synchronized/serialized! It means, that expected to call callbacks of observer in the serialized way to follow observable contract: "Observables must issue notifications to observers serially (not in parallel).". If you are not sure or need extra serialization, please, use serialized_subject.
*
* @tparam Type value provided by this subject
*
* @ingroup subjects
* @see https://reactivex.io/documentation/subject.html
*/
template<rpp::constraint::decayed_type Type>
class publish_subject final : public details::base_subject<Type, details::publish_strategy<Type>>
{
public:
using details::base_subject<Type, details::publish_strategy<Type>>::base_subject;
};
}
18 changes: 17 additions & 1 deletion src/rpp/rpp/subjects/serialized_subject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,20 @@ class serialized_strategy
private:
std::shared_ptr<serialized_state> m_state = std::make_shared<serialized_state>();
};
} // namespace rpp::subjects::details
} // namespace rpp::subjects::details

namespace rpp::subjects
{
/**
* @brief Same as rpp::subjects::publish_subject, but on_next/on_error/on_completed calls are serialized via mutex
*
* @ingroup subjects
* @see https://reactivex.io/documentation/subject.html
*/
template<rpp::constraint::decayed_type Type>
class serialized_subject final : public details::base_subject<Type, details::serialized_strategy<Type>>
{
public:
using details::base_subject<Type, details::serialized_strategy<Type>>::base_subject;
};
}
18 changes: 7 additions & 11 deletions src/rpp/rpp/utils/function_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#pragma once

#include <tuple>
#include <rpp/utils/tuple.hpp>
#include <type_traits>

namespace rpp::utils
Expand Down Expand Up @@ -73,19 +73,15 @@ template<class R, class... Args>
struct function_traits<R (*)(Args...)>
{
using result = R;
using arguments = std::tuple<Args...>;
using arguments = rpp::utils::tuple<std::decay_t<Args>...>;

template<std::size_t i = 0>
requires (sizeof...(Args) > i)
using argument = std::tuple_element_t<i, arguments>;
template<std::size_t I = 0>
requires (sizeof...(Args) > I)
using argument = typename arguments::template type_at_index_t<I>;
};

template<typename T, std::size_t i = 0>
using function_argument_t = typename function_traits<T>::template argument<i>;


template<typename T, std::size_t i = 0>
using decayed_function_argument_t = std::decay_t<function_argument_t<T, i>>;
template<typename T, std::size_t I = 0>
using decayed_function_argument_t = typename function_traits<T>::template argument<I>;

template<typename Fn, typename... Args>
using decayed_invoke_result_t = std::decay_t<std::invoke_result_t<Fn, Args...>>;
Expand Down
8 changes: 6 additions & 2 deletions src/rpp/rpp/utils/tuple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,16 @@ class RPP_EMPTY_BASES tuple_impl<std::index_sequence<Indices...>, Args...> : pri

private:
template<size_t I, typename T>
constexpr static T type_at_index(const tuple_leaf<I, T>&);
constexpr static T type_at_index_impl(const tuple_leaf<I, T>*);

public:

template<size_t I>
constexpr static auto type_at_index() -> decltype(type_at_index_impl<I>(std::declval<tuple_impl*>()));

template<size_t I>
requires (I < sizeof...(Args))
using type_at_index_t = decltype(type_at_index<I>(std::declval<tuple_impl>()));
using type_at_index_t = decltype(type_at_index<I>());
};
}

Expand Down
19 changes: 19 additions & 0 deletions src/rpp/rpp/utils/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <rpp/defs.hpp>
#include <rpp/utils/constraints.hpp>
#include <rpp/utils/tuple.hpp>

#include <algorithm>

Expand All @@ -30,6 +31,24 @@ struct types
template<constraint::iterable T>
using iterable_value_t = std::iter_value_t<decltype(std::begin(std::declval<T>()))>;

namespace details
{
template<template<typename...> typename Base>
struct traits
{
template<typename... Types>
constexpr static rpp::utils::tuple<Types...> extract_params(const Base<Types...>*);
constexpr static std::false_type extract_params(...);
};
}

template<typename T, template <typename...> typename Base>
concept is_base_of_v = !std::is_same_v<decltype(details::traits<Base>::extract_params(std::declval<std::decay_t<T>*>())), std::false_type>;

template<typename T, template <typename...> typename Base>
requires is_base_of_v<T, Base>
using extract_base_type_params_t = decltype(details::traits<Base>::extract_params(std::declval<std::decay_t<T>*>()));

template<class T>
constexpr std::add_const_t<T>& as_const(const T& v) noexcept
{
Expand Down