TL; DR
сделать явное приведение (как cdeterman сделал) или явный вызов конструктора:
// [[Rcpp::export]]
Rcpp::IntegerVector fun_bad() {
Rcpp::IntegerVector newOffer =
RcppArmadillo::sample(Rcpp::IntegerVector(seq_len(5)), 1, true);
return newOffer;
}
Не цитируйте меня на специфику, но я m довольно уверен, что вы столкнулись с краевым случаем Expression Templates, не играющим красиво с правилами вычитания типа шаблона. Во-первых, соответствующая часть сообщения об ошибке, излучаемый мой компилятор:
... В конкретизации «T Rcpp :: RcppArmadillo :: образца (сопзЬ T &, INT, BOOL, Rcpp :: NumericVector) [с T = Rcpp :: sugar :: SeqLen; ...
Следовательно, в templated sample
function, T
выводится как имеющий тип Rcpp::sugar::SeqLen
.
SeqLen
является шаблонным классом выражения - defined here - которые, в большинстве случаев, будет (неявно) преобразуется в Rcpp::IntegerVector
(из-за его наследство от Rcpp::VectorBase<INTSXP, ...>
).Например,
// [[Rcpp::export]]
Rcpp::IntegerVector test(int n = 5) {
return Rcpp::seq_len(5); // Ok
}
Однако, поскольку неявные преобразования являются частью процесса разрешения перегрузки, а не процесс дедукции типа шаблона, T
выводится точно так, как Rcpp::sugar::SeqLen
- значит это выражение
ret[ii] = x[jj];
является вызывающий Rcpp::sugar::SeqLen::operator[]
(и неRcpp::Vector::operator[]
, как это обычно бывает), который производит rvalue (см. ниже †).
Вы могли заметить, что в отличие от некоторых классов ET sugar
, SeqLen
является более «истинным» шаблон выражения в том, что он просто обеспечивает operator[]
для того, лениво оценены. Он не сохраняет постоянный элемент ссылочных данных/предоставляет оператор векторного преобразования (как, например, cumprod
и многие другие); она буквально используется для построения вектора - this constructor, если я не ошибаюсь,
template <bool NA, typename VEC>
Vector(const VectorBase<RTYPE,NA,VEC>& other) {
RCPP_DEBUG_2("Vector<%d>(const VectorBase<RTYPE,NA,VEC>&) [VEC = %s]", RTYPE, DEMANGLE(VEC))
import_sugar_expression(other, typename traits::same_type<Vector,VEC>::type()) ;
}
, который использует следующие вспомогательные методы, определенные в классе Vector
:
// we are importing a real sugar expression, i.e. not a vector
template <bool NA, typename VEC>
inline void import_sugar_expression(const Rcpp::VectorBase<RTYPE,NA,VEC>& other, traits::false_type) {
RCPP_DEBUG_4("Vector<%d>::import_sugar_expression(VectorBase<%d,%d,%s>, false_type)", RTYPE, NA, RTYPE, DEMANGLE(VEC)) ;
R_xlen_t n = other.size() ;
Storage::set__(Rf_allocVector(RTYPE, n)) ;
import_expression<VEC>(other.get_ref() , n) ;
}
template <typename T>
inline void import_expression(const T& other, int n) {
iterator start = begin() ;
RCPP_LOOP_UNROLL(start,other)
}
Во всяком случае, до тех пор Rcpp автоматически генерирует фактический векторный объект из выражения sugar::SeqLen
, он недоступен для использования (по крайней мере, так, как это требуется в этом конкретном выражении: ret[ii] = x[jj];
).
† Так же, как проверки вменяемости, мы можем использовать несколько C++ 11 метапрограммирования конструкций изучить разницу между возвращаемых значений SeqLen::operator[]
и Vector::operator[]
:
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadilloExtensions/sample.h>
typedef decltype(Rcpp::sugar::SeqLen(1)[0]) rvalue_t;
typedef decltype(Rcpp::IntegerVector::create(1)[0]) lvalue_ref_t;
// [[Rcpp::export]]
void test() {
// rvalue_t is an rvalue
Rcpp::Rcout
<< std::is_rvalue_reference<rvalue_t&&>::value
<< "\n";
// lvalue_ref_t is an lvalue
Rcpp::Rcout
<< std::is_lvalue_reference<lvalue_ref_t>::value
<< "\n";
// rvalue_t is _not_ assignable
Rcpp::Rcout
<< std::is_assignable<rvalue_t, R_xlen_t>::value
<< "\n";
// lvalue_ref_t is assignable
Rcpp::Rcout
<< std::is_assignable<lvalue_ref_t, R_xlen_t>::value
<< "\n";
}
/*** R
test()
# 1 ## true
# 1 ## true
# 0 ## false
# 1 ## true
*/
Хорошая работа, как обычно. Upvoted. –