aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/deps/rpclib/include/rpc/detail/call.h
blob: b5c9bdce0c0be95691750d71675e4b324d84d2be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#pragma once

#ifndef CALL_H_ZXFACADH
#define CALL_H_ZXFACADH

#include <tuple>
#include "rpc/detail/func_tools.h"
#include "rpc/detail/invoke.h"
#include "rpc/detail/is_specialization_of.h"

namespace rpc {
namespace detail {

//! \brief Calls a functor with argument provided directly
template <typename Functor, typename Arg>
auto call(Functor f, Arg &&arg)
    -> decltype(f(std::forward<Arg>(arg)))
{
    return f(std::forward<Arg>(arg));
}


// Default behaviour is to assume C++11, overriding RPCLIB_CXX_STANDARD can use
// newer standards:
#if RPCLIB_CXX_STANDARD >= 14

template <typename Functor, typename... Args, std::size_t... I>
decltype(auto) call_helper(Functor func, std::tuple<Args...> &&params,
                           std::index_sequence<I...>) {
    return func(std::get<I>(params)...);
}

//! \brief Calls a functor with arguments provided as a tuple
template <typename Functor, typename... Args>
decltype(auto) call(Functor f, std::tuple<Args...> &args) {
    return call_helper(f, std::forward<std::tuple<Args...>>(args),
                       std::index_sequence_for<Args...>{});
}

#else

// N is number of arguments left in tuple to unpack

template <size_t N>
struct call_helper
{
    template <typename Functor, typename... ArgsT, typename... ArgsF>
    static auto call(
            Functor f,
            std::tuple<ArgsT...>& args_t,
            ArgsF&&... args_f)
    -> decltype(call_helper<N-1>::call(
                f, args_t, std::get<N-1>(args_t),
                std::forward<ArgsF>(args_f)...))
    {
        return call_helper<N-1>::call(
                f,
                args_t,
                std::get<N-1>(args_t),
                std::forward<ArgsF>(args_f)...
        );
    }
};

template <>
struct call_helper<0>
{
    template <typename Functor, typename... ArgsT, typename... ArgsF>
    static auto call(
            Functor f,
            std::tuple<ArgsT...>&,
            ArgsF&&... args_f)
    -> decltype(f(std::forward<ArgsF>(args_f)...))
    {
        return f(std::forward<ArgsF>(args_f)...);
    }
};

//! \brief Calls a functor with arguments provided as a tuple
template <typename Functor, typename... ArgsT>
auto call(Functor f, std::tuple<ArgsT...>& args_t)
    -> decltype(call_helper<sizeof...(ArgsT)>::call(f, args_t))
{
    return call_helper<sizeof...(ArgsT)>::call(f, args_t);
}

#endif

}
}

#endif /* end of include guard: CALL_H_ZXFACADH */