mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-19 06:26:55 +00:00
Use 'if constexpr ()' instead of tag dispatch.
This commit is contained in:
parent
5cc7cb1d85
commit
ea0f6b9a12
@ -187,29 +187,14 @@ optional_wrap_once_t<Type> make_optional(Type &&value) {
|
||||
return optional_wrap_once_t<Type> { std::forward<Type>(value) };
|
||||
}
|
||||
|
||||
template <typename Type, typename Method>
|
||||
inline auto optional_chain(
|
||||
const optional<Type> &value,
|
||||
Method &method,
|
||||
std::false_type)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
return value ? make_optional(method(*value)) : none;
|
||||
}
|
||||
|
||||
template <typename Type, typename Method>
|
||||
inline auto optional_chain(
|
||||
const optional<Type> &value,
|
||||
Method &method,
|
||||
std::true_type)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
return value ? (method(*value), true) : false;
|
||||
}
|
||||
|
||||
template <typename Type, typename Method>
|
||||
inline auto operator|(const optional<Type> &value, Method method)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
using is_void_return = std::is_same<decltype(method(*value)), void>;
|
||||
return optional_chain(value, method, is_void_return {});
|
||||
if constexpr (std::is_same_v<decltype(method(*value)), void>) {
|
||||
return value ? (method(*value), true) : false;
|
||||
} else {
|
||||
return value ? make_optional(method(*value)) : none;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
@ -43,25 +43,16 @@ inline span<const char> make_span(const QByteArray &cont) {
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
template <typename D, typename T>
|
||||
inline constexpr D up_cast_helper(std::true_type, T object) {
|
||||
return object;
|
||||
}
|
||||
|
||||
template <typename D, typename T>
|
||||
inline constexpr D up_cast_helper(std::false_type, T object) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename D, typename T>
|
||||
inline constexpr D up_cast(T object) {
|
||||
using DV = std::decay_t<decltype(*D())>;
|
||||
using TV = std::decay_t<decltype(*T())>;
|
||||
return internal::up_cast_helper<D>(std::integral_constant<bool, std::is_base_of<DV, TV>::value || std::is_same<DV, TV>::value>(), object);
|
||||
if constexpr (std::is_base_of_v<DV, TV>) {
|
||||
return object;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container, typename T>
|
||||
|
@ -257,16 +257,6 @@ template <typename ...Args>
|
||||
constexpr bool combine_producers_with_mapper_v
|
||||
= combine_producers_with_mapper<Args...>::value;
|
||||
|
||||
template <
|
||||
typename ...Values,
|
||||
typename ...Errors,
|
||||
typename ...Generators>
|
||||
inline decltype(auto) combine_helper(
|
||||
std::true_type,
|
||||
producer<Values, Errors, Generators> &&...producers) {
|
||||
return combine_implementation(std::move(producers)...);
|
||||
}
|
||||
|
||||
template <typename ...Producers, std::size_t ...I>
|
||||
inline decltype(auto) combine_call(
|
||||
std::index_sequence<I...>,
|
||||
@ -275,18 +265,6 @@ inline decltype(auto) combine_call(
|
||||
argument_mapper<I>::call(std::move(producers)...)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline decltype(auto) combine_helper(
|
||||
std::false_type,
|
||||
Args &&...args) {
|
||||
constexpr auto kProducersCount = sizeof...(Args) - 1;
|
||||
return combine_call(
|
||||
std::make_index_sequence<kProducersCount>(),
|
||||
std::forward<Args>(args)...)
|
||||
| map(argument_mapper<kProducersCount>::call(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
template <
|
||||
@ -295,9 +273,18 @@ template <
|
||||
details::combine_just_producers_v<Args...>
|
||||
|| details::combine_producers_with_mapper_v<Args...>>>
|
||||
inline decltype(auto) combine(Args &&...args) {
|
||||
return details::combine_helper(
|
||||
details::combine_just_producers<Args...>(),
|
||||
std::forward<Args>(args)...);
|
||||
if constexpr (details::combine_just_producers_v<Args...>) {
|
||||
return details::combine_implementation(std::move(args)...);
|
||||
} else if constexpr (details::combine_producers_with_mapper_v<Args...>) {
|
||||
constexpr auto kProducersCount = sizeof...(Args) - 1;
|
||||
return details::combine_call(
|
||||
std::make_index_sequence<kProducersCount>(),
|
||||
std::forward<Args>(args)...)
|
||||
| map(details::argument_mapper<kProducersCount>::call(
|
||||
std::forward<Args>(args)...));
|
||||
} else {
|
||||
static_assert(false_(args...), "Bad combine() call.");
|
||||
}
|
||||
}
|
||||
|
||||
namespace details {
|
||||
|
@ -86,6 +86,10 @@ struct is_type_erased_handlers<type_erased_handlers<Value, Error>>
|
||||
: std::true_type {
|
||||
};
|
||||
|
||||
template <typename Handlers>
|
||||
constexpr bool is_type_erased_handlers_v
|
||||
= is_type_erased_handlers<Handlers>::value;
|
||||
|
||||
template <typename Value, typename Error, typename OnNext, typename OnError, typename OnDone>
|
||||
class consumer_handlers final
|
||||
: public type_erased_handlers<Value, Error> {
|
||||
@ -285,7 +289,8 @@ namespace details {
|
||||
|
||||
template <typename Value, typename Error, typename Handlers>
|
||||
class consumer_base {
|
||||
using is_type_erased = is_type_erased_handlers<Handlers>;
|
||||
static constexpr bool is_type_erased
|
||||
= is_type_erased_handlers_v<Handlers>;
|
||||
|
||||
public:
|
||||
template <
|
||||
@ -345,44 +350,22 @@ private:
|
||||
|
||||
mutable std::shared_ptr<Handlers> _handlers;
|
||||
|
||||
bool handlers_put_next(Value &&value, std::true_type) const {
|
||||
return _handlers->put_next(std::move(value));
|
||||
bool handlers_put_next(Value &&value) const {
|
||||
if constexpr (is_type_erased) {
|
||||
return _handlers->put_next(std::move(value));
|
||||
} else {
|
||||
return _handlers->Handlers::put_next(std::move(value));
|
||||
}
|
||||
}
|
||||
bool handlers_put_next_copy(
|
||||
const Value &value,
|
||||
std::true_type) const {
|
||||
return _handlers->put_next_copy(value);
|
||||
bool handlers_put_next_copy(const Value &value) const {
|
||||
if constexpr (is_type_erased) {
|
||||
return _handlers->put_next_copy(value);
|
||||
} else {
|
||||
return _handlers->Handlers::put_next_copy(value);
|
||||
}
|
||||
}
|
||||
void handlers_put_error(Error &&error, std::true_type) const {
|
||||
return std::exchange(_handlers, nullptr)->put_error(std::move(error));
|
||||
}
|
||||
void handlers_put_error_copy(
|
||||
const Error &error,
|
||||
std::true_type) const {
|
||||
return std::exchange(_handlers, nullptr)->put_error_copy(error);
|
||||
}
|
||||
void handlers_put_done(std::true_type) const {
|
||||
return std::exchange(_handlers, nullptr)->put_done();
|
||||
}
|
||||
|
||||
bool handlers_put_next(Value &&value, std::false_type) const {
|
||||
return _handlers->Handlers::put_next(std::move(value));
|
||||
}
|
||||
bool handlers_put_next_copy(
|
||||
const Value &value,
|
||||
std::false_type) const {
|
||||
return _handlers->Handlers::put_next_copy(value);
|
||||
}
|
||||
void handlers_put_error(Error &&error, std::false_type) const {
|
||||
return std::exchange(_handlers, nullptr)->Handlers::put_error(std::move(error));
|
||||
}
|
||||
void handlers_put_error_copy(
|
||||
const Error &error,
|
||||
std::false_type) const {
|
||||
return std::exchange(_handlers, nullptr)->Handlers::put_error_copy(error);
|
||||
}
|
||||
void handlers_put_done(std::false_type) const {
|
||||
return std::exchange(_handlers, nullptr)->Handlers::put_done();
|
||||
std::shared_ptr<Handlers> take_handlers() const {
|
||||
return std::exchange(_handlers, nullptr);
|
||||
}
|
||||
|
||||
template <
|
||||
@ -408,7 +391,7 @@ template <typename Value, typename Error, typename Handlers>
|
||||
inline bool consumer_base<Value, Error, Handlers>::put_next(
|
||||
Value &&value) const {
|
||||
if (_handlers) {
|
||||
if (handlers_put_next(std::move(value), is_type_erased())) {
|
||||
if (handlers_put_next(std::move(value))) {
|
||||
return true;
|
||||
}
|
||||
_handlers = nullptr;
|
||||
@ -420,7 +403,7 @@ template <typename Value, typename Error, typename Handlers>
|
||||
inline bool consumer_base<Value, Error, Handlers>::put_next_copy(
|
||||
const Value &value) const {
|
||||
if (_handlers) {
|
||||
if (handlers_put_next_copy(value, is_type_erased())) {
|
||||
if (handlers_put_next_copy(value)) {
|
||||
return true;
|
||||
}
|
||||
_handlers = nullptr;
|
||||
@ -432,7 +415,11 @@ template <typename Value, typename Error, typename Handlers>
|
||||
inline void consumer_base<Value, Error, Handlers>::put_error(
|
||||
Error &&error) const {
|
||||
if (_handlers) {
|
||||
handlers_put_error(std::move(error), is_type_erased());
|
||||
if constexpr (is_type_erased) {
|
||||
take_handlers()->put_error(std::move(error));
|
||||
} else {
|
||||
take_handlers()->Handlers::put_error(std::move(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,14 +427,22 @@ template <typename Value, typename Error, typename Handlers>
|
||||
inline void consumer_base<Value, Error, Handlers>::put_error_copy(
|
||||
const Error &error) const {
|
||||
if (_handlers) {
|
||||
handlers_put_error_copy(error, is_type_erased());
|
||||
if constexpr (is_type_erased) {
|
||||
take_handlers()->put_error_copy(error);
|
||||
} else {
|
||||
take_handlers()->Handlers::put_error_copy(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Value, typename Error, typename Handlers>
|
||||
inline void consumer_base<Value, Error, Handlers>::put_done() const {
|
||||
if (_handlers) {
|
||||
handlers_put_done(is_type_erased());
|
||||
if constexpr (is_type_erased) {
|
||||
take_handlers()->put_done();
|
||||
} else {
|
||||
take_handlers()->Handlers::put_done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,54 +99,19 @@ struct is_callable<Method, Arg>
|
||||
template <typename Method, typename ...Args>
|
||||
constexpr bool is_callable_v = is_callable<Method, Args...>::value;
|
||||
|
||||
enum class CallableArgTag {
|
||||
Plain,
|
||||
Tuple,
|
||||
Empty,
|
||||
};
|
||||
template <CallableArgTag Arg>
|
||||
using callable_arg_tag = std::integral_constant<CallableArgTag, Arg>;
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) callable_helper(
|
||||
Method &&method,
|
||||
Arg &&arg,
|
||||
callable_arg_tag<CallableArgTag::Plain>) {
|
||||
return std::forward<Method>(method)(std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) callable_helper(
|
||||
Method &&method,
|
||||
Arg &&arg,
|
||||
callable_arg_tag<CallableArgTag::Tuple>) {
|
||||
return std::apply(
|
||||
std::forward<Method>(method),
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) callable_helper(
|
||||
Method &&method,
|
||||
Arg &&,
|
||||
callable_arg_tag<CallableArgTag::Empty>) {
|
||||
return std::forward<Method>(method)();
|
||||
}
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) callable_invoke(Method &&method, Arg &&arg) {
|
||||
// #TODO if constexpr
|
||||
constexpr auto kTag = is_callable_plain_v<Method, Arg>
|
||||
? CallableArgTag::Plain
|
||||
: is_callable_tuple_v<Method, Arg>
|
||||
? CallableArgTag::Tuple
|
||||
: is_callable_v<Method>
|
||||
? CallableArgTag::Empty
|
||||
: throw "Bad callable_invoke instance.";
|
||||
return callable_helper(
|
||||
std::forward<Method>(method),
|
||||
std::forward<Arg>(arg),
|
||||
callable_arg_tag<kTag>());
|
||||
if constexpr (is_callable_plain_v<Method, Arg>) {
|
||||
return std::forward<Method>(method)(std::forward<Arg>(arg));
|
||||
} else if constexpr (is_callable_tuple_v<Method, Arg>) {
|
||||
return std::apply(
|
||||
std::forward<Method>(method),
|
||||
std::forward<Arg>(arg));
|
||||
} else if constexpr (is_callable_v<Method>) {
|
||||
return std::forward<Method>(method)();
|
||||
} else {
|
||||
static_assert(false_(method, arg), "Bad callable_invoke() call.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
@ -167,39 +132,18 @@ constexpr bool allows_const_ref_v = (sizeof(test_allows_const_ref(
|
||||
std::declval<Method>(),
|
||||
std::declval<Arg>())) == sizeof(true_t));
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
struct allows_const_ref
|
||||
: std::bool_constant<
|
||||
allows_const_ref_v<Method, Arg>> {
|
||||
};
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) const_ref_call_helper(
|
||||
Method &&method,
|
||||
const Arg &arg,
|
||||
std::true_type) {
|
||||
return callable_invoke(std::forward<Method>(method), arg);
|
||||
}
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) const_ref_call_helper(
|
||||
Method &&method,
|
||||
const Arg &arg,
|
||||
std::false_type) {
|
||||
auto copy = arg;
|
||||
return callable_invoke(
|
||||
std::forward<Method>(method),
|
||||
std::move(copy));
|
||||
}
|
||||
|
||||
template <typename Method, typename Arg>
|
||||
inline decltype(auto) const_ref_call_invoke(
|
||||
Method &&method,
|
||||
const Arg &arg) {
|
||||
return const_ref_call_helper(
|
||||
std::forward<Method>(method),
|
||||
arg,
|
||||
allows_const_ref<Method, Arg>());
|
||||
if constexpr (allows_const_ref_v<Method, Arg>) {
|
||||
return callable_invoke(std::forward<Method>(method), arg);
|
||||
} else {
|
||||
auto copy = arg;
|
||||
return callable_invoke(
|
||||
std::forward<Method>(method),
|
||||
std::move(copy));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
Loading…
Reference in New Issue
Block a user