2017-02-21 38 views
1

考慮下面的類,它絕對沒有:模板RCPP的類返回元素::矢量<RTYPE>

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工作?

+3

作爲參考,常規方法來做到這在C++ 98是到模板上的基本類'SEXPTYPE'並使用'Rcpp :: traits :: storage_type'來確定原子類型。 [例如](https://gist.github.com/nathan-russell/a6c154ae18d2a5cc8dcc3af06da01ea6#file-vector-template-cpp)。 – nrussell

+1

@nrussell你能寫出這個要點嗎?這是'auto'例子的一個可行的替代方案。我有點害怕它可能會在SO的混亂中迷失方向。 – coatless

回答

4

如果您需要堅持使用C++ 98,通常的習慣用法是使用整數模板參數來表示the different SEXPTYPEs。當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¹型 - >SEXPTYPEr_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)不同,並且不,例如如預期的那樣,可以使用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" 
+1

像往常一樣美妙的帖子@nrussell。 – coatless

3

auto返回類型扣除無追溯返回類型是一個C++ 14語言功能。

auto operator[](int i) const -> decltype(x[i]) { 
    return x[i]; 
} 

在上面的代碼,auto將被「取代」與x[i]類型:在C++ 11,可以作爲在添加後返回類型使用auto只要。

+1

上週末我寫了一篇關於Rcpp和C++ 11,C++ 14和C++ 17的Rcpp圖片庫(http://gallery.rcpp.org/articles/rcpp-and-C++ 11-C++ 14-C++ 17 /)碰巧將'auto'顯示爲返回類型。當然是用C++ 14。 –