Reputation: 7474
Consider the following class that does absolutely nothing:
class MyNumVec
{
private:
const NumericVector& x;
public:
MyNumVec(const NumericVector& y) : x(y) {}
double operator[](int i) const { // here
return x[i];
}
operator NumericVector() const { return x; }
};
I would like to make it more general and use template for it so that I'll be working with any Vector<RTYPE>
instead of numeric vectors only, but the problem is the line marked by comment since I must declare output type. I tried using auto
type from C++11, but it doesn't work ("'auto' return without trailing return type
"). How can this be translated to template working with Vector
of any type?
Upvotes: 1
Views: 403
Reputation: 18612
If you need to stick to C++98, the usual idiom is to use an integer template parameter to represent the different SEXPTYPE
s. When dealing with Rcpp::*Vector
(or Rcpp::*Matrix
) you are typically only concerned with 5 of these:
# Integer Value SEXPTYPE R Vector Rcpp Vector
# 10 LGLSXP logical LogicalVector
# 13 INTSXP integer IntegerVector
# 14 REALSXP numeric NumericVector
# 15 CPLXSXP complex ComplexVector
# 16 STRSXP character CharacterVector
Having done this, there are standard metaprogramming tools for commonly needed transformations in the Rcpp::traits
namespace:
SEXPTYPE
-> POD¹ type: storage_type
Rcpp::traits::storage_type<REALSXP>::type
-> double
Rcpp::traits::storage_type<INTSXP>::type
-> int
SEXPTYPE
: r_sexptype_traits
Rcpp::traits::r_sexptype_traits<double>::rtype
-> 14 (REALSXP
)Rcpp::traits::r_sexptype_traits<int>::rtype
-> 13 (INTSXP
)¹storage_type<STRSXP>::type
yields SEXP
(specifically, a CHARSXP
), and while technically a POD type, it differs from the other simple vector types in that its atomic unit is an opaque pointer (a SEXP
), and not, e.g. a const char*
or std::string
as might be expected.
An uninteresting example, using RCPP_RETURN_VECTOR
for conciseness:
#include <Rcpp.h>
template <int RTYPE>
class MyNumVec {
public:
typedef Rcpp::Vector<RTYPE> vec_t;
typedef typename Rcpp::traits::storage_type<RTYPE>::type storage_t;
private:
const vec_t& x;
public:
MyNumVec(const vec_t& y)
: x(y)
{}
storage_t operator[](int i) const
{ return x[i]; }
operator vec_t() const
{ return x; }
};
template <int RTYPE>
Rcpp::Vector<RTYPE> get_first_elem_impl(const Rcpp::Vector<RTYPE>& vec)
{
MyNumVec<RTYPE> tmp(vec);
return Rcpp::Vector<RTYPE>::create(tmp[0]);
}
// [[Rcpp::export]]
Rcpp::RObject get_first_elem(Rcpp::RObject x) {
RCPP_RETURN_VECTOR(get_first_elem_impl, x);
}
get_first_elem(c(TRUE, TRUE, FALSE, TRUE, FALSE))
# [1] TRUE
get_first_elem(1L:5L)
# [1] 1
get_first_elem(1:5 + 0.5)
# [1] 1.5
get_first_elem(1:5 + 2i)
# [1] 1+2i
get_first_elem(letters[1:5])
# [1] "a"
Upvotes: 7
Reputation: 93334
auto
return type deduction without a trailing return type is a C++14 language feature. In C++11, you can use auto
as long as you add a trailing return type:
auto operator[](int i) const -> decltype(x[i]) {
return x[i];
}
In the code above, auto
will be "replaced" with the type of x[i]
.
Upvotes: 3