2017-11-08 3 views
1

다음 MWE가 있습니다. 여기에는 정수와 문자열이라는 두 개의 멤버가있는 클래스가 들어 있습니다. first 함수를 사용하여 클래스의 객체를 만들고 그에 대한 포인터를 반환합니다. second_intsecond_str에는 두 멤버가 출력됩니다.Rcpp : 템플릿 기능 구성

second_intsecond_str이 어느 정도 동일한 기능을 가지고 있다고 가정하면 템플릿을 만드는 것이 분명해 보입니다. 내 MWE 주어진 Rcpp 내에서 할 수 있습니까?

class C{ 
public: 
    std::vector<int> i_vec; 
    std::vector<std::string> s_vec; 

    C(){ 
    i_vec.push_back(0); 
    s_vec.push_back("R"); 
    } 
}; 

// [[Rcpp::export]] 
XPtr<C> first() 
{ 
    XPtr<C> p(new C, true); 
    return(p); 
} 

// [[Rcpp::export]] 
void second_int(XPtr<C> p) 
{ 
    Rcout << p->i_vec[0] << "\n"; 
} 

// [[Rcpp::export]] 
void second_str(XPtr<C> p) 
{ 
    Rcout << p->s_vec[0] << "\n"; 
} 
+0

기능은 외부와 비슷하게 보이지만 내부적으로는 매우 다른 두 가지 작업을 수행합니다. 이들을 하나의 함수로 병합하려는 시도는 틀림없이 틀림없이 틀림 없습니다. 나는 당신이 그것들을 그대로있는 채로 두거나, 그들이 작동하는 벡터 유형에 대한 함수를 매개 변수화할 것을 제안한다. 즉 C에 대한 포인터가 아닌 벡터를 전달합니다 – smac89

+0

왜 템플릿을 템플릿으로 만드시겠습니까? 입력/출력은 동일합니다 :'void'와'XPtr'. 두 가지 기능이 있습니다. 이 코드는 올바르게 들립니다. – JRR

답변

2

템플릿을 여기 직접 사용할 수는 없지만 원하는대로 만들 수 있습니다. 당신이 쓴 것을 생각해보고 과 같은 것을 직접 작성하는 것으로 보입니다.

// [[Rcpp::export]] 
void second_int(XPtr<C> p) 
{ 
    Rcout << p->i_vec[0] << "\n"; 
} 

// [[Rcpp::export]] 
void second_str(XPtr<C> p) 
{ 
    Rcout << p->s_vec[0] << "\n"; 
} 

당신이이 (이 유효 C++되지 않음) 싶은 것이 :

당신은이

// [[Rcpp::export]] 
template< membername member_to_extract > 
void second(XPtr<C> p) 
{ 
    Rcout << p->member_to_extract[0] << "\n"; 
} 

/** 
* we would like to call it like this: 
* second<i_vec>(p) (to get the int value) 
* second<s_vec>(p) (to get the str value) 
*/ 

하지 않는 이유는이 작품? 음, http://en.cppreference.com/w/cpp/language/template_parameters을 확인하면 템플릿 매개 변수로 변수 이름을 전달할 수 없습니다. 따라서이 접근법은 실패 할 운명입니다. (참고 :! 이것에 대한 당신 사용 매크로, 당신이 찾고있는 해결책이 될 수 있습니다) 당신의 기능을 인수하면서,

그러나 및 유형이 동일 반환, 그들의 행동 는 오직 결과로는 당신이 함께 가고 싶은 타입. 이미 템플리트 화 된 컨텍스트에서 이러한 함수를 사용하려는 경우 두 번째 및 두 번째 인터페이스를 얻는 것이 바람직합니다.

구조에 템플릿 전문화!

// generic template. We need something that fails to compile 
// so that second<int> and second<std::string> are the only 
// specializations the compiler will allow us to use. 
template< typename T > 
void second(XPtr<C> p) 
{ 
    static_assert(false, "second can't be used with this type."); 
} 

template< > 
void second<int>(XPtr<C> p) 
{ 
    Rcout << p->i_vec[0] << "\n"; 
} 

template< > 
void second<std::string>(XPtr<C> p) 
{ 
    Rcout << p->s_vec[0] << "\n"; 
} 

나는 이것이 당신이 원하는 것이라고 생각합니까? 플랫폼이 라인 버퍼가 아닌 경우 "\ n"대신 std :: endl을 사용하는 것이 좋습니다. 플러시를 강제 실행하므로 (아마도 원하는 동작 일 것입니다).

편집 : 부분 전문화 -> 템플리트 특수화