c++ - 在不知道实际内部数据类型的情况下返回给定 SEXP 的子集
问题描述
我正在编写一个R 包来提供调试帮助函数,以打印s和s 数据类型的gdb
变量值。R
SEXP
Rcpp
C/C++ 是一种强类型语言,但我想避免查询 s 的内部数据类型,SEXP
并使用一堆if
s 进行硬编码调度。
我如何通过这样的函数签名使用索引范围来实现通用子集函数:
SEXP dbg_subset(SEXP x, R_xlen_t index_from, R_xlen_t index_to);
一种可能的解决方案是为每个可能的签名编写上述函数,例如。对于INTSXP
, LGLSXP
, STRSXP
... 但我很懒 ;-)
注意:我不能使用 C++ 模板,因为链接器只会为我的 C++ 代码中使用的数据类型创建模板实例(与“正在调试的库”中的不同),并且gdb
没有编译器可以创建当输入 C++ 表达式以查询变量时,“即时”丢失模板实例。
编辑:查看这个答案(但它基于我想避免的模板):
解决方案
您可以将 C++ 模板与RCPP_RETURN_VECTOR
宏一起使用。此宏将确保为所有(?) R 数据类型实例化模板:
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
template <int RTYPE>
Rcpp::Vector<RTYPE> debug_subset_impl(Rcpp::Vector<RTYPE> x,
R_xlen_t index_from,
R_xlen_t index_to){
// range [index_from, index_to)
Rcpp::Vector<RTYPE> subset(index_to - index_from);
std::copy(x.cbegin() + index_from, x.cbegin() + index_to, subset.begin());
// special case for factors == INTSXP with "class" and "levels" attribute
if (x.hasAttribute("levels")){
subset.attr("class") = x.attr("class");
subset.attr("levels") = x.attr("levels");
}
return subset;
}
// [[Rcpp::export]]
SEXP dbg_subset(SEXP x, R_xlen_t index_from, R_xlen_t index_to){
// 1-based -> 0-based
RCPP_RETURN_VECTOR(debug_subset_impl, x, index_from - 1, index_to - 1);
}
/*** R
set.seed(42)
dbg_subset(1:100, 3, 6)
dbg_subset(runif(100), 3, 6)
dbg_subset(letters, 3, 6)
dbg_subset(as.factor(letters), 3, 6)
*/
输出:
> Rcpp::sourceCpp('58965423.cpp')
> set.seed(42)
> dbg_subset(1:100, 3, 6)
[1] 3 4 5
> dbg_subset(runif(100), 3, 6)
[1] 0.2861395 0.8304476 0.6417455
> dbg_subset(letters, 3, 6)
[1] "c" "d" "e"
> dbg_subset(as.factor(letters), 3, 6)
[1] c d e
Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z
推荐阅读
- r - 将数据框的感兴趣框合并到同一列中
- paypal-sandbox - 无法在 paypal API 中更新沙盒帐户 (PRICING_SCHEME_UPDATE_NOT_ALLOWED) 中的计划定价
- java - 是否可以在 JCommander 中解析命令行参数而不提供参数名称?
- python - 如何区分参数为 None 或 Python 中不存在?
- algorithm - 快速 2D 有符号距离
- python - 由部分 keras 进行培训 whit trainable
- android - 片段的添加功能不适用于 viewBinding
- youtube - 为什么频道管理员不能上传或编辑视频以对域私有?
- node.js - 如何解决 cors 起源异常
- java - 这是从 android 的 Firebase 数据库中以小块加载数据的正确方法吗?