class 返回 Rcpp::Vector<RTYPE> 元素的模板
Template for class returning elements of Rcpp::Vector<RTYPE>
考虑以下完全没有任何作用的 class:
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; }
};
我想让它更通用并为其使用模板,这样我就可以使用任何 Vector<RTYPE>
而不是仅使用数字向量,但问题是注释标记的行,因为我必须声明输出类型。我尝试使用 C++11 中的 auto
类型,但它不起作用(“'auto' return without trailing return type
”)。如何将其转换为使用任何类型的 Vector
的模板?
auto
return 没有 尾随 return 类型的类型推导 是 C++14 语言功能。在C++11中,你可以使用auto
只要你添加一个尾随return类型:
auto operator[](int i) const -> decltype(x[i]) {
return x[i];
}
在上面的代码中,auto
将是 "replaced",类型为 x[i]
。
如果你需要坚持使用 C++98,通常的习惯用法是使用整数模板参数来表示 the different SEXPTYPE
s。在处理 Rcpp::*Vector
(或 Rcpp::*Matrix
)时,您通常只关心其中的 5 个:
# 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
完成此操作后,Rcpp::traits
命名空间中有用于通常需要的转换的标准元编程工具:
SEXPTYPE
-> POD¹ 类型:storage_type
Rcpp::traits::storage_type<REALSXP>::type
-> double
Rcpp::traits::storage_type<INTSXP>::type
-> int
- 等等
- POD¹ 类型 ->
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
产生 SEXP
(具体来说,CHARSXP
),虽然 技术上 是 POD 类型,但它与其他类型不同简单的向量类型,因为它的原子单元是一个不透明的指针(SEXP
),而不是,例如a const char*
或 std::string
如预期的那样。
一个无趣的例子,为简洁起见使用RCPP_RETURN_VECTOR
:
#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"
考虑以下完全没有任何作用的 class:
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; }
};
我想让它更通用并为其使用模板,这样我就可以使用任何 Vector<RTYPE>
而不是仅使用数字向量,但问题是注释标记的行,因为我必须声明输出类型。我尝试使用 C++11 中的 auto
类型,但它不起作用(“'auto' return without trailing return type
”)。如何将其转换为使用任何类型的 Vector
的模板?
auto
return 没有 尾随 return 类型的类型推导 是 C++14 语言功能。在C++11中,你可以使用auto
只要你添加一个尾随return类型:
auto operator[](int i) const -> decltype(x[i]) {
return x[i];
}
在上面的代码中,auto
将是 "replaced",类型为 x[i]
。
如果你需要坚持使用 C++98,通常的习惯用法是使用整数模板参数来表示 the different SEXPTYPE
s。在处理 Rcpp::*Vector
(或 Rcpp::*Matrix
)时,您通常只关心其中的 5 个:
# 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
完成此操作后,Rcpp::traits
命名空间中有用于通常需要的转换的标准元编程工具:
SEXPTYPE
-> POD¹ 类型:storage_type
Rcpp::traits::storage_type<REALSXP>::type
->double
Rcpp::traits::storage_type<INTSXP>::type
->int
- 等等
- POD¹ 类型 ->
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
产生 SEXP
(具体来说,CHARSXP
),虽然 技术上 是 POD 类型,但它与其他类型不同简单的向量类型,因为它的原子单元是一个不透明的指针(SEXP
),而不是,例如a const char*
或 std::string
如预期的那样。
一个无趣的例子,为简洁起见使用RCPP_RETURN_VECTOR
:
#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"