tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
invoke_result.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2019 Tobias Hienzsch
3
4#ifndef TETL_TYPE_TRAITS_INVOKE_RESULT_HPP
5#define TETL_TYPE_TRAITS_INVOKE_RESULT_HPP
6
7#include <etl/_type_traits/bool_constant.hpp>
8#include <etl/_type_traits/decay.hpp>
9#include <etl/_type_traits/declval.hpp>
10#include <etl/_type_traits/is_base_of.hpp>
11#include <etl/_type_traits/is_function.hpp>
12#include <etl/_type_traits/is_reference_wrapper.hpp>
13#include <etl/_utility/forward.hpp>
14
15namespace etl {
16
17namespace detail {
18
19template <typename T>
20struct invoke_impl {
21 template <typename F, typename... Args>
22 static auto call(F&& f, Args&&... args) -> decltype(etl::forward<F>(f)(etl::forward<Args>(args)...));
23};
24
25template <typename B, typename MT>
26struct invoke_impl<MT B::*> {
27 template <typename T, typename Td = decay_t<T>>
28 requires is_base_of_v<B, Td>
29 static auto get(T&& t) -> T&&;
30
31 template <typename T, typename Td = decay_t<T>>
32 requires is_reference_wrapper<Td>::value
33 static auto get(T&& t) -> decltype(t.get());
34
35 template <typename T, typename Td = decay_t<T>>
36 requires(!is_base_of_v<B, Td> and !is_reference_wrapper<Td>::value)
37 static auto get(T&& t) -> decltype(*etl::forward<T>(t));
38
39 template <typename T, typename... Args, typename MT1>
40 requires is_function_v<MT1>
41 static auto call(MT1 B::* pmf, T&& t, Args&&... args)
42 -> decltype((invoke_impl::get(etl::forward<T>(t)).*pmf)(etl::forward<Args>(args)...));
43
44 template <typename T>
45 static auto call(MT B::* pmd, T&& t) -> decltype(invoke_impl::get(etl::forward<T>(t)).*pmd);
46};
47
48template <typename F, typename... Args, typename Fd = decay_t<F>>
49auto INVOKE(F&& f, Args&&... args) -> decltype(invoke_impl<Fd>::call(etl::forward<F>(f), etl::forward<Args>(args)...));
50
51template <typename AlwaysVoid, typename, typename...>
52struct invoke_result { };
53
54template <typename F, typename... Args>
55struct invoke_result<decltype(void(detail::INVOKE(declval<F>(), declval<Args>()...))), F, Args...> {
56 using type = decltype(detail::INVOKE(declval<F>(), declval<Args>()...));
57};
58
59} // namespace detail
60
61/// Deduces the return type of an INVOKE expression at compile time.
62///
63/// F and all types in ArgTypes can be any complete type, array of unknown
64/// bound, or (possibly cv-qualified) void. The behavior of a program that adds
65/// specializations for any of the templates described on this page is
66/// undefined. This implementation is copied from **cppreference.com**.
67///
68/// https://en.cppreference.com/w/cpp/types/result_of
69///
70/// \ingroup type_traits
71template <typename F, typename... ArgTypes>
72struct invoke_result : detail::invoke_result<void, F, ArgTypes...> { };
73
74/// \relates invoke_result
75/// \ingroup type_traits
76template <typename F, typename... ArgTypes>
77using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
78
79} // namespace etl
80
81#endif // TETL_TYPE_TRAITS_INVOKE_RESULT_HPP
Definition adjacent_find.hpp:9
Deduces the return type of an INVOKE expression at compile time.
Definition invoke_result.hpp:72
Definition is_reference_wrapper.hpp:15