我有一个vector<boost::function<void(void)>>
-本质上是类似函数的对象的向量。向量包含一些Rcpp::Function
对象以及一些boost::function<void(void)>
对象。
对此我有两个问题。首先,我不太了解它是如何工作的,因为据我所知,Rcpp::Function
不是boost::function
的子类。向量如何存储这些不具有相同类的对象? (或者他们以某种方式共享课程?)
第二,更重要的是,我希望能够在运行时自省对象。我想遍历向量并返回它的Rcpp::List
表示形式:任何Rcpp::Function
对象将被添加到列表中,而任何boost::function
对象将简单地由任意字符串表示,像"C++ function"
。
在下面的示例中,我有一个C ++函数test
,该函数将Rcpp::Function
作为输入并添加到向量中。它还向向量添加boost::function<void(void)>
。然后遍历列表,执行每个功能。我还没有弄清的最后一部分是如何构建List
,其中添加到列表中的项目取决于每个项目的类型。这可能吗?
library(Rcpp)
cppFunction(
includes = '
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
void cpp_message(std::string s) {
std::cerr << s << "\\n";
}
',
code = '
Rcpp::List test(Rcpp::Function r_fn) {
std::vector<boost::function0<void> > fns;
// Add a Rcpp::Function to the vector
fns.push_back(r_fn);
// Add a boost::function<void(void)> to the vector
boost::function<void(void)> cpp_fn = boost::bind(&cpp_message, "bar");
fns.push_back(cpp_fn);
// Execute the functions to demonstrate the vector works
for (int i=0; i<fns.size(); i++) {
fns[i]();
}
// Create the List
Rcpp::List result;
for (int i=0; i<fns.size(); i++) {
// What I would like to do is something like:
// if (fns[i] is a Rcpp::Function) {
// result[i] = fns[i];
// } else {
// result[i] = "C++ function";
// }
}
return result;
}
',
depends = "BH"
)
test(function() message("foo"))
#> foo
#> bar
#> list()
(请注意,输出行的顺序可能会有所不同,具体取决于环境如何缓冲输出,因此您可能会看到其输出顺序不同。)
答案 0 :(得分:2)
向量如何存储这些不具有相同类的对象?
好吧,不是直接存储此类对象的向量,而是在向量内部新创建的boost::function
对象将存储实例。该对象将如何操作?
一些简单的演示类说明了如何实现此 :
// first need a generic template allowing the Demo<void(void)> syntax
template <typename S>
class Demo;
// now specialising (otherwise, we'd need to instantiate Demo<void, void>)
template <typename R, typename ... PP>
class Demo<R(PP...)>
{
class Wrapper
{
public:
virtual ~Wrapper() { }
virtual R operator()(PP...) = 0;
};
template <typename T>
class SpecificWrapper : public Wrapper
{
T t;
public:
SpecificWrapper(T& t) : t(t) { };
virtual R operator()(PP...pp) { return t(pp...); }
};
// the trick: pointer to POLYMORPHIC type!
Wrapper* w;
public:
// be aware that this constructor deliberately is NOT explicit
template <typename T>
Demo(T& t) : w(new SpecificWrapper<T>(t)) { }
R operator()(PP...pp) { return (*w)(pp...); }
};
非显式构造函数允许隐式创建一个新的Demo对象:
Rcpp::Function r; // simplified just for demo!
std::vector<Demo<void(void)>> v;
v.push_back(r); // implicit call to non-explicit constructor! equivalent to:
v.push_back(Demo<void(void)>(r));
请注意,该类仅实现了最少的操作(仅是复制构造函数;可能尚未添加move构造函数和适当的赋值运算符),因为该类仅用于演示目的。
我希望能够在运行时自检对象。
您正在寻找std::function::target:
auto l = []() { std::cout << "demo" << std::endl; };
std::function<void(void)> f(l);
auto* pl = f.target<decltype(l)>();
if(pl)
(*pl)();
但是,这闻起来有点糟糕的设计,就像需要dynamic_cast
(Demo
最有可能在其target
变体中用于包装指针)一样。您为什么要找回这个?您是否只是想像Rcpp一样处理所有功能?