Rcpp Version 1.0.9
dispatch.h
Go to the documentation of this file.
1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2 //
3 // dispatch.h: Rcpp R/C++ interface class library -- macros for dispatch
4 //
5 // Copyright (C) 2012 - 2016 Dirk Eddelbuettel and Romain Francois
6 // Copyright (C) 2016 Dirk Eddelbuettel, Romain Francois, Artem Klevtsov and Nathan Russell
7 //
8 // This file is part of Rcpp.
9 //
10 // Rcpp is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // Rcpp is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef Rcpp__macros__dispatch_h
24 #define Rcpp__macros__dispatch_h
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 
33 #ifdef RCPP_USING_CXX11
34 
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  }
55 
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 
80 #else
81 
82 #define ___RCPP_HANDLE_CASE___(___RTYPE___, ___FUN___, ___OBJECT___, \
83  ___RCPPTYPE___) \
84  case ___RTYPE___: \
85  return ___FUN___(::Rcpp::___RCPPTYPE___<___RTYPE___>(___OBJECT___));
86 
87 #define ___RCPP_RETURN___(__FUN__, __SEXP__, __RCPPTYPE__) \
88  SEXP __TMP__ = __SEXP__; \
89  switch (TYPEOF(__TMP__)) { \
90  ___RCPP_HANDLE_CASE___(INTSXP, __FUN__, __TMP__, __RCPPTYPE__) \
91  ___RCPP_HANDLE_CASE___(REALSXP, __FUN__, __TMP__, __RCPPTYPE__) \
92  ___RCPP_HANDLE_CASE___(RAWSXP, __FUN__, __TMP__, __RCPPTYPE__) \
93  ___RCPP_HANDLE_CASE___(LGLSXP, __FUN__, __TMP__, __RCPPTYPE__) \
94  ___RCPP_HANDLE_CASE___(CPLXSXP, __FUN__, __TMP__, __RCPPTYPE__) \
95  ___RCPP_HANDLE_CASE___(STRSXP, __FUN__, __TMP__, __RCPPTYPE__) \
96  ___RCPP_HANDLE_CASE___(VECSXP, __FUN__, __TMP__, __RCPPTYPE__) \
97  ___RCPP_HANDLE_CASE___(EXPRSXP, __FUN__, __TMP__, __RCPPTYPE__) \
98  default: \
99  throw std::range_error("Not a vector"); \
100  }
101 
102 #define RCPP_RETURN_VECTOR(_FUN_, _SEXP_) \
103  ___RCPP_RETURN___(_FUN_, _SEXP_, Vector)
104 #define RCPP_RETURN_MATRIX(_FUN_, _SEXP_) \
105  ___RCPP_RETURN___(_FUN_, _SEXP_, Matrix)
106 #endif
107 
108 #endif