File: call.h

package info (click to toggle)
rcpp 1.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,480 kB
  • sloc: cpp: 27,436; ansic: 7,778; sh: 53; makefile: 2
file content (53 lines) | stat: -rw-r--r-- 2,074 bytes parent folder | download
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
#ifndef RCPP_INTERNAL_CALL_H
#define RCPP_INTERNAL_CALL_H

#include <Rcpp/traits/index_sequence.h>
#include <functional>

namespace Rcpp {
namespace internal {
// Utility struct so that we can pass a pack of types between functions
template <typename... T> struct type_pack {};

/**
 * This specialisation is for functions that return a value, whereas the below
 * is for void-returning functions.
 *
 * The "* = nullptr" default argument allows both templates to be well-defined
 * regardless of which one is used.
 */
template <typename F, typename RESULT_TYPE, typename... Us, int... Is,
            typename std::enable_if<!std::is_void<RESULT_TYPE>::value>::type* = nullptr>
SEXP call_impl(const F& fun, SEXP* args, type_pack<RESULT_TYPE, Us...>,
                traits::index_sequence<Is...>) {
    RESULT_TYPE res = fun((typename traits::input_parameter<Us>::type(args[Is]))...);
    return Rcpp::module_wrap<RESULT_TYPE>(res);
}

template <typename F, typename RESULT_TYPE, typename... Us, int... Is,
            typename std::enable_if<std::is_void<RESULT_TYPE>::value>::type* = nullptr>
SEXP call_impl(const F& fun, SEXP* args, type_pack<RESULT_TYPE, Us...>,
                traits::index_sequence<Is...>) {
    fun((typename traits::input_parameter<Us>::type(args[Is]))...);
    return R_NilValue;
}
} // namespace internal

/**
 * Helper for calling a function with an array of SEXP arguments,
 * where each argument is converted to the appropriate type before being passed
 * to the function. A compile-time sequence is used to index the SEXP array.
 *
 * The function only needs the intended types of the result and arguments,
 *  which allows the template to be used for function pointers, lambdas, and
 * `std::function` objects.
 */
template <typename F, typename RESULT_TYPE, typename... Us>
SEXP call(const F& fun, SEXP* args) {
    return internal::call_impl(fun, args,
                                internal::type_pack<RESULT_TYPE, Us...>{},
                                traits::make_index_sequence<sizeof...(Us)>{});
}
} // namespace Rcpp

#endif