2017-02-21 19 views
1

は絶対に何もしない次のクラスを考えてみましょう:テンプレート::ベクトル<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>となりますが、出力タイプを宣言する必要があるので、問題はコメントでマークされた行です。私はautoタイプをC++ 11から試しましたが、動作しません( "'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

@nurlsell代わりに要点を書くことができますか?これは 'auto'の例の実行可能な代替手段です。私はそれがそうでなければそれの混乱で失われるかもしれないことを少し恐れている。 – coatless

答えて

4

C++ 98に固執する必要がある場合、通常のイディオムは整数テンプレートパラメータを使用してthe different SEXPTYPEsを表すことです。あなたは一般的にこれらの5を有する唯一の懸念しているRcpp::*Vector(またはRcpp::*Matrix)を扱う場合:

# 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

いつものように素晴らしい投稿@nurussell。 – coatless

3

autoなし返品タイプ控除なし末尾返品タイプはC++ 14言語機能です。上記のコードで

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

autox[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では、もちろんです。 –