|
3 | 3 | // dispatch.h: Rcpp R/C++ interface class library -- macros for dispatch |
4 | 4 | // |
5 | 5 | // Copyright (C) 2012 - 2016 Dirk Eddelbuettel and Romain Francois |
6 | | -// Copyright (C) 2016 Dirk Eddelbuettel, Romain Francois and Artem Klevtsov |
| 6 | +// Copyright (C) 2016 Dirk Eddelbuettel, Romain Francois, Artem Klevtsov and Nathan Russell |
7 | 7 | // |
8 | 8 | // This file is part of Rcpp. |
9 | 9 | // |
|
23 | 23 | #ifndef Rcpp__macros__dispatch_h |
24 | 24 | #define Rcpp__macros__dispatch_h |
25 | 25 |
|
| 26 | +// The variadic macros below incorporate techniques presented by |
| 27 | +// Stack Overflow user Richard Hansen in this answer |
| 28 | +// |
| 29 | +// http://stackoverflow.com/a/11172679/1869097 |
| 30 | +// |
| 31 | +// and are necessary to avoid the use of GNU compiler extensions. |
| 32 | + |
26 | 33 | #ifdef RCPP_USING_CXX11 |
27 | | -#define ___RCPP_HANDLE_CASE___(___RTYPE___, ___FUN___, ___OBJECT___, \ |
28 | | - ___RCPPTYPE___, ...) \ |
29 | | - case ___RTYPE___: \ |
30 | | - return ___FUN___(::Rcpp::___RCPPTYPE___<___RTYPE___>(___OBJECT___), \ |
31 | | - ##__VA_ARGS__); |
32 | 34 |
|
33 | | -#define ___RCPP_RETURN___(__FUN__, __SEXP__, __RCPPTYPE__, ...) \ |
34 | | - SEXP __TMP__ = __SEXP__; \ |
35 | | - switch (TYPEOF(__TMP__)) { \ |
36 | | - ___RCPP_HANDLE_CASE___(INTSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
37 | | - ##__VA_ARGS__) \ |
38 | | - ___RCPP_HANDLE_CASE___(REALSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
39 | | - ##__VA_ARGS__) \ |
40 | | - ___RCPP_HANDLE_CASE___(RAWSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
41 | | - ##__VA_ARGS__) \ |
42 | | - ___RCPP_HANDLE_CASE___(LGLSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
43 | | - ##__VA_ARGS__) \ |
44 | | - ___RCPP_HANDLE_CASE___(CPLXSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
45 | | - ##__VA_ARGS__) \ |
46 | | - ___RCPP_HANDLE_CASE___(STRSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
47 | | - ##__VA_ARGS__) \ |
48 | | - ___RCPP_HANDLE_CASE___(VECSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
49 | | - ##__VA_ARGS__) \ |
50 | | - ___RCPP_HANDLE_CASE___(EXPRSXP, __FUN__, __TMP__, __RCPPTYPE__, \ |
51 | | - ##__VA_ARGS__) \ |
52 | | - default: \ |
53 | | - throw std::range_error("Not a vector"); \ |
| 35 | +#define ___RCPP_HANDLE_CASE___(___RTYPE___, ___FUN___, ___RCPPTYPE___, ...) \ |
| 36 | + case ___RTYPE___: \ |
| 37 | + return ___FUN___(::Rcpp::___RCPPTYPE___<___RTYPE___>(RCPP_MACRO_FIRST(__VA_ARGS__)) \ |
| 38 | + RCPP_MACRO_REST(__VA_ARGS__)); |
| 39 | + |
| 40 | + |
| 41 | +#define ___RCPP_RETURN___(__FUN__, __RCPPTYPE__, ...) \ |
| 42 | + SEXP __TMP__ = RCPP_MACRO_FIRST(__VA_ARGS__); \ |
| 43 | + switch (TYPEOF(__TMP__)) { \ |
| 44 | + ___RCPP_HANDLE_CASE___(INTSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 45 | + ___RCPP_HANDLE_CASE___(REALSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 46 | + ___RCPP_HANDLE_CASE___(RAWSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 47 | + ___RCPP_HANDLE_CASE___(LGLSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 48 | + ___RCPP_HANDLE_CASE___(CPLXSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 49 | + ___RCPP_HANDLE_CASE___(STRSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 50 | + ___RCPP_HANDLE_CASE___(VECSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 51 | + ___RCPP_HANDLE_CASE___(EXPRSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ |
| 52 | + default: \ |
| 53 | + throw std::range_error("Not a vector"); \ |
54 | 54 | } |
55 | 55 |
|
56 | | -#define RCPP_RETURN_VECTOR(_FUN_, _SEXP_, ...) \ |
57 | | - ___RCPP_RETURN___(_FUN_, _SEXP_, Vector, ##__VA_ARGS__) |
58 | | -#define RCPP_RETURN_MATRIX(_FUN_, _SEXP_, ...) \ |
59 | | - ___RCPP_RETURN___(_FUN_, _SEXP_, Matrix, ##__VA_ARGS__) |
| 56 | + |
| 57 | +#define RCPP_RETURN_VECTOR(_FUN_, ...) \ |
| 58 | + ___RCPP_RETURN___(_FUN_, Vector, __VA_ARGS__) |
| 59 | +#define RCPP_RETURN_MATRIX(_FUN_, ...) \ |
| 60 | + ___RCPP_RETURN___(_FUN_, Matrix, __VA_ARGS__) |
| 61 | + |
| 62 | + |
| 63 | +#define RCPP_MACRO_FIRST(...) RCPP_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway) |
| 64 | +#define RCPP_MACRO_FIRST_HELPER(first, ...) first |
| 65 | + |
| 66 | +#define RCPP_MACRO_REST(...) RCPP_MACRO_REST_HELPER(RCPP_MACRO_NUM(__VA_ARGS__), __VA_ARGS__) |
| 67 | +#define RCPP_MACRO_REST_HELPER(qty, ...) RCPP_MACRO_REST_HELPER2(qty, __VA_ARGS__) |
| 68 | +#define RCPP_MACRO_REST_HELPER2(qty, ...) RCPP_MACRO_REST_HELPER_##qty(__VA_ARGS__) |
| 69 | +#define RCPP_MACRO_REST_HELPER_ONE(first) |
| 70 | +#define RCPP_MACRO_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__ |
| 71 | +#define RCPP_MACRO_NUM(...) \ |
| 72 | + RCPP_MACRO_SELECT_25TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ |
| 73 | + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ |
| 74 | + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ |
| 75 | + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ |
| 76 | + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) |
| 77 | +#define RCPP_MACRO_SELECT_25TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, \ |
| 78 | + a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, ...) a25 |
| 79 | + |
60 | 80 | #else |
| 81 | + |
61 | 82 | #define ___RCPP_HANDLE_CASE___(___RTYPE___, ___FUN___, ___OBJECT___, \ |
62 | 83 | ___RCPPTYPE___) \ |
63 | 84 | case ___RTYPE___: \ |
|
0 commit comments