Skip to content

Commit 9ef99cb

Browse files
author
Daniel C. Dillon
committed
Added decays_to_ctype as well for better control of which iterators can be passed to these functions
1 parent ca1a13b commit 9ef99cb

File tree

1 file changed

+73
-27
lines changed

1 file changed

+73
-27
lines changed

inst/include/Rcpp/algorithm.h

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -64,49 +64,49 @@ namespace helpers {
6464
typedef struct {char a[128];} CTYPE_UNKNOWN;
6565

6666
template< std::size_t I >
67-
struct ctype_helper { };
67+
struct ctype_helper { static const bool value = false; };
6868

6969
template<>
70-
struct ctype_helper< sizeof(CTYPE_CHAR) > { typedef char type; };
70+
struct ctype_helper< sizeof(CTYPE_CHAR) > { typedef char type; static const bool value = true; };
7171

7272
template<>
73-
struct ctype_helper< sizeof(CTYPE_SHORT) > { typedef short type; };
73+
struct ctype_helper< sizeof(CTYPE_SHORT) > { typedef short type; static const bool value = true; };
7474

7575
template<>
76-
struct ctype_helper< sizeof(CTYPE_INT) > { typedef int type; };
76+
struct ctype_helper< sizeof(CTYPE_INT) > { typedef int type; static const bool value = true; };
7777

7878
template<>
79-
struct ctype_helper< sizeof(CTYPE_LONG) > { typedef long type; };
79+
struct ctype_helper< sizeof(CTYPE_LONG) > { typedef long type; static const bool value = true; };
8080

8181
template<>
82-
struct ctype_helper< sizeof(CTYPE_LONG_LONG) > { typedef long long type; };
82+
struct ctype_helper< sizeof(CTYPE_LONG_LONG) > { typedef long long type; static const bool value = true; };
8383

8484
template<>
85-
struct ctype_helper< sizeof(CTYPE_FLOAT) > { typedef float type; };
85+
struct ctype_helper< sizeof(CTYPE_FLOAT) > { typedef float type; static const bool value = true; };
8686

8787
template<>
88-
struct ctype_helper< sizeof(CTYPE_DOUBLE) > { typedef double type; };
88+
struct ctype_helper< sizeof(CTYPE_DOUBLE) > { typedef double type; static const bool value = true; };
8989

9090
template<>
91-
struct ctype_helper< sizeof(CTYPE_LONG_DOUBLE) > { typedef long double type; };
91+
struct ctype_helper< sizeof(CTYPE_LONG_DOUBLE) > { typedef long double type; static const bool value = true; };
9292

9393
template<>
94-
struct ctype_helper< sizeof(CTYPE_STRING) > { typedef std::string type; };
94+
struct ctype_helper< sizeof(CTYPE_STRING) > { typedef std::string type; static const bool value = true; };
9595

9696
template<>
97-
struct ctype_helper< sizeof(CTYPE_UNSIGNED_CHAR) > { typedef unsigned char type; };
97+
struct ctype_helper< sizeof(CTYPE_UNSIGNED_CHAR) > { typedef unsigned char type; static const bool value = true; };
9898

9999
template<>
100-
struct ctype_helper< sizeof(CTYPE_UNSIGNED_SHORT) > { typedef unsigned short type; };
100+
struct ctype_helper< sizeof(CTYPE_UNSIGNED_SHORT) > { typedef unsigned short type; static const bool value = true; };
101101

102102
template<>
103-
struct ctype_helper< sizeof(CTYPE_UNSIGNED_INT) > { typedef unsigned int type; };
103+
struct ctype_helper< sizeof(CTYPE_UNSIGNED_INT) > { typedef unsigned int type; static const bool value = true; };
104104

105105
template<>
106-
struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG) > { typedef unsigned long type; };
106+
struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG) > { typedef unsigned long type; static const bool value = true; };
107107

108108
template<>
109-
struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG_LONG) > { typedef unsigned long long type; };
109+
struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG_LONG) > { typedef unsigned long long type; static const bool value = true; };
110110

111111

112112
template< typename T >
@@ -133,6 +133,30 @@ namespace helpers {
133133
typedef typename ctype_helper< sizeof(test(make())) >::type type;
134134
};
135135

136+
template< typename T >
137+
struct decays_to_ctype
138+
{
139+
static CTYPE_CHAR test(const char &);
140+
static CTYPE_SHORT test(const short &);
141+
static CTYPE_INT test(const int &);
142+
static CTYPE_LONG test(const long &);
143+
static CTYPE_LONG_LONG test(const long long &);
144+
static CTYPE_FLOAT test(const float &);
145+
static CTYPE_DOUBLE test(const double &);
146+
static CTYPE_LONG_DOUBLE test(const long double &);
147+
static CTYPE_STRING test(const std::string &);
148+
static CTYPE_UNSIGNED_CHAR test(const unsigned char &);
149+
static CTYPE_UNSIGNED_SHORT test(const unsigned short &);
150+
static CTYPE_UNSIGNED_INT test(const unsigned int &);
151+
static CTYPE_UNSIGNED_LONG test(const unsigned long &);
152+
static CTYPE_UNSIGNED_LONG_LONG test(const unsigned long long &);
153+
static CTYPE_UNKNOWN test(...);
154+
155+
static T make();
156+
157+
static const bool value = ctype_helper< sizeof(test(make())) >::value;
158+
};
159+
136160
struct log {
137161
template< typename T >
138162
inline double operator()(T val) {
@@ -168,7 +192,9 @@ namespace helpers {
168192
} // namespace helpers
169193

170194
template< typename InputIterator >
171-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type sum(InputIterator begin, InputIterator end) {
195+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
196+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
197+
sum(InputIterator begin, InputIterator end) {
172198

173199
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
174200
typedef typename helpers::rtype< value_type > rtype;
@@ -191,7 +217,9 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
191217
}
192218

193219
template< typename InputIterator >
194-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type sum_nona(InputIterator begin, InputIterator end) {
220+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
221+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
222+
sum_nona(InputIterator begin, InputIterator end) {
195223

196224
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
197225
typedef typename helpers::rtype< value_type > rtype;
@@ -210,7 +238,9 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
210238
}
211239

212240
template< typename InputIterator >
213-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type prod(InputIterator begin, InputIterator end) {
241+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
242+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
243+
prod(InputIterator begin, InputIterator end) {
214244

215245
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
216246
typedef typename helpers::rtype< value_type > rtype;
@@ -233,7 +263,9 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
233263
}
234264

235265
template< typename InputIterator >
236-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type prod_nona(InputIterator begin, InputIterator end) {
266+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
267+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
268+
prod_nona(InputIterator begin, InputIterator end) {
237269

238270
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
239271
typedef typename helpers::rtype< value_type > rtype;
@@ -252,7 +284,10 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
252284
}
253285

254286
template< typename InputIterator >
255-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type max(InputIterator begin, InputIterator end) {
287+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
288+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
289+
max(InputIterator begin, InputIterator end) {
290+
256291
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
257292
typedef typename helpers::rtype< value_type > rtype;
258293

@@ -274,7 +309,10 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
274309
}
275310

276311
template< typename InputIterator >
277-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type max_nona(InputIterator begin, InputIterator end) {
312+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
313+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
314+
max_nona(InputIterator begin, InputIterator end) {
315+
278316
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
279317
typedef typename helpers::rtype< value_type > rtype;
280318

@@ -292,7 +330,10 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
292330
}
293331

294332
template< typename InputIterator >
295-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type min(InputIterator begin, InputIterator end) {
333+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
334+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
335+
min(InputIterator begin, InputIterator end) {
336+
296337
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
297338
typedef typename helpers::rtype< value_type > rtype;
298339

@@ -314,7 +355,10 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
314355
}
315356

316357
template< typename InputIterator >
317-
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type min_nona(InputIterator begin, InputIterator end) {
358+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value,
359+
typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
360+
min_nona(InputIterator begin, InputIterator end) {
361+
318362
typedef typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type value_type;
319363
typedef typename helpers::rtype< value_type > rtype;
320364

@@ -333,8 +377,9 @@ typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_t
333377

334378
// for REALSXP
335379
template< typename InputIterator >
336-
typename traits::enable_if< traits::same_type< typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type, double >::value, double >::type
337-
mean(InputIterator begin, InputIterator end)
380+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value
381+
&& traits::same_type< typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type, double >::value, double >::type
382+
mean(InputIterator begin, InputIterator end)
338383
{
339384
if (begin != end)
340385
{
@@ -359,8 +404,9 @@ mean(InputIterator begin, InputIterator end)
359404

360405
// for LGLSXP and INTSXP
361406
template< typename InputIterator >
362-
typename traits::enable_if< traits::same_type< typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type, int >::value, double >::type
363-
mean(InputIterator begin, InputIterator end)
407+
typename traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value
408+
&& traits::same_type< typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type, int >::value, double >::type
409+
mean(InputIterator begin, InputIterator end)
364410
{
365411
if (begin != end)
366412
{

0 commit comments

Comments
 (0)