Rcpp:构造模板函数
Rcpp: Constructing templated functions
我有以下 MWE。它包含一个 class 和两个成员,一个整数和一个字符串。使用函数 first
我创建了一个 class 的对象和 return 一个指向它的指针。在 second_int
和 second_str
中,我输出了两个成员。
鉴于 second_int
和 second_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";
}
模板在这里不能直接使用,但是我们可以用它来完成我想你想要的!让我们考虑一下您已经写的内容以及您喜欢直接写的内容。
你有:
// [[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,我们发现您不能将变量名作为模板参数传入!所以这种做法注定要失败。 (注意:您可以为此使用宏,这可能是您正在寻找的解决方案!)
然而,虽然您的函数参数和 return 类型相同,但它们的行为 是 完全取决于您要使用的类型。如果您打算在已经模板化的上下文中使用这些函数,那么最好获得第二个和第二个接口!
模板专业化来拯救!
// 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";
}
我想这就是你想要的?请注意,如果您的平台不是行缓冲的,您可能想使用 std::endl 而不是“\n”,因为它会强制刷新(这可能是您想要的行为)。
编辑:部分专业化 -> 模板专业化
我有以下 MWE。它包含一个 class 和两个成员,一个整数和一个字符串。使用函数 first
我创建了一个 class 的对象和 return 一个指向它的指针。在 second_int
和 second_str
中,我输出了两个成员。
鉴于 second_int
和 second_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";
}
模板在这里不能直接使用,但是我们可以用它来完成我想你想要的!让我们考虑一下您已经写的内容以及您喜欢直接写的内容。
你有:
// [[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,我们发现您不能将变量名作为模板参数传入!所以这种做法注定要失败。 (注意:您可以为此使用宏,这可能是您正在寻找的解决方案!)
然而,虽然您的函数参数和 return 类型相同,但它们的行为 是 完全取决于您要使用的类型。如果您打算在已经模板化的上下文中使用这些函数,那么最好获得第二个和第二个接口!
模板专业化来拯救!
// 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";
}
我想这就是你想要的?请注意,如果您的平台不是行缓冲的,您可能想使用 std::endl 而不是“\n”,因为它会强制刷新(这可能是您想要的行为)。
编辑:部分专业化 -> 模板专业化