/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Extensions to the Result type to enable simpler handling of XPCOM/NSPR
* results. */
// Allow nsresult errors to automatically convert to nsresult values, so MOZ_TRY // can be used in XPCOM methods with Result<T, nserror> results. template <> class [[nodiscard]] GenericErrorResult<nsresult> {
nsresult mErrorValue;
template <typename R, typename E, typename RArgMapper, typename Func, typename... Args>
Result<R, E> ToResultInvokeInternal(const Func& aFunc, const RArgMapper& aRArgMapper,
Args&&... aArgs) { // XXX Thereotically, if R is a pointer to a non-refcounted type, this might // be a non-owning pointer, but unless we find a case where this actually is // relevant, it's safe to forbid any raw pointer result.
static_assert(
!std::is_pointer_v<R>, "Raw pointer results are not supported, please specify a smart pointer " "result type explicitly, so that getter_AddRefs is used");
R res;
nsresult rv = aFunc(std::forward<Args>(aArgs)..., aRArgMapper(res)); if (NS_FAILED(rv)) { return Err(ResultTypeTraits<E>::From(rv));
} return res;
}
template <typename T> struct outparam_as_pointer;
template <typename T> struct outparam_as_pointer<T*> { using type = T*;
};
// There are two ToResultInvokeSelector overloads, which cover the cases of a) a // pointer-typed output parameter, and b) a reference-typed output parameter, // using to_result_retval_t in connection with outparam_as_pointer and // outparam_as_reference type traits. These type traits may be specialized for // types other than raw pointers to allow calling functions with argument types // that implicitly convert/bind to a raw pointer/reference. The overload that is // used is selected by expression SFINAE: the decltype expression in // to_result_retval_t is only valid in either case. template <typename R, typename E, typename Func, typename... Args> auto ToResultInvokeSelector(const Func& aFunc, Args&&... aArgs)
-> to_result_retval_t<R, E, outparam_as_pointer, Func, Args...> { return ToResultInvokeInternal<R, E>(
aFunc, [](R& res) -> decltype(auto) { return ResultRefAsParam(res); },
std::forward<Args>(aArgs)...);
}
/** * Adapts a function with a nsresult error type and an R* output parameter as * the last parameter to a function returning a mozilla::Result<R, nsresult> * object. * * This can also be used with member functions together with std::men_fn, e.g. * * nsCOMPtr<nsIFile> file = ...; * auto existsOrErr = ToResultInvoke<bool>(std::mem_fn(&nsIFile::Exists), * *file); * * but it is more convenient to use the member function version, which has the * additional benefit of enabling the deduction of the success result type: * * nsCOMPtr<nsIFile> file = ...; * auto existsOrErr = ToResultInvokeMember(*file, &nsIFile::Exists);
*/ template <typename R, typename E = nsresult, typename Func, typename... Args>
Result<R, E> ToResultInvoke(const Func& aFunc, Args&&... aArgs) { return detail::ToResultInvokeSelector<R, E, Func, Args&&...>(
aFunc, std::forward<Args>(aArgs)...);
}
namespace detail { template <typename T> struct tag { using type = T;
};
template <typename... Ts> struct select_last { using type = typename decltype((tag<Ts>{}, ...))::type;
};
template <typename... Ts> using select_last_t = typename select_last<Ts...>::type;
template <> struct select_last<> { using type = void;
};
template <typename E, typename RArg, typename T, typename Func, typename... Args> auto ToResultInvokeMemberInternal(T& aObj, const Func& aFunc, Args&&... aArgs) { if constexpr (std::is_pointer_v<RArg> ||
(std::is_lvalue_reference_v<RArg> &&
!std::is_const_v<std::remove_reference_t<RArg>>)) { auto lambda = [&](RArg res) { return (aObj.*aFunc)(std::forward<Args>(aArgs)..., res);
}; return detail::ToResultInvokeSelector<
std::remove_reference_t<std::remove_pointer_t<RArg>>, E,
decltype(lambda)>(lambda);
} else { // No output parameter present, return a Result<Ok, E> return mozilla::ToResult<E>((aObj.*aFunc)(std::forward<Args>(aArgs)...));
}
}
// For use in MOZ_TO_RESULT_INVOKE_MEMBER/MOZ_TO_RESULT_INVOKE_MEMBER_TYPED. template <typename T> auto DerefHelper(const T&) -> T&;
template <typename T> auto DerefHelper(T*) -> T&;
template <template <class> class SmartPtr, typename T, typename = decltype(*std::declval<const SmartPtr<T>>())> auto DerefHelper(const SmartPtr<T>&) -> T&;
// Macro version of ToResultInvokeMember for member functions. The macro has // the advantage of not requiring spelling out the member function's declarator // type name, at the expense of having a non-standard syntax. It can be used // like this: // // nsCOMPtr<nsIFile> file; // auto existsOrErr = MOZ_TO_RESULT_INVOKE_MEMBER(file, Exists); #define MOZ_TO_RESULT_INVOKE_MEMBER(obj, methodname, ...) \
::mozilla::ToResultInvokeMember( \
(obj), &::mozilla::detail::DerefedType<decltype(obj)>::methodname, \ ##__VA_ARGS__)
// Macro version of ToResultInvokeMember for member functions, where the result // type does not match the output parameter type. The macro has the advantage // of not requiring spelling out the member function's declarator type name, at // the expense of having a non-standard syntax. It can be used like this: // // nsCOMPtr<nsIFile> file; // auto existsOrErr = // MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsCOMPtr<nsIFile>, file, Clone); #define MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(resultType, obj, methodname, ...) \
::mozilla::ToResultInvoke<MOZ_REMOVE_PAREN(resultType)>( \
::std::mem_fn( \
&::mozilla::detail::DerefedType<decltype(obj)>::methodname), \
(obj), ##__VA_ARGS__)
} // namespace mozilla
#endif// mozilla_ResultExtensions_h
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.