我正在尝试使用variate模板编写自己的apply函数。这是我的代码:
template<typename...>
struct types{
};
template<typename T, typename... Args>
struct Func{
template<typename F, typanem... Types>
T call(F f, std::tuple<Types...>& params, Args... args){
return _call(f, params, types<Types...>{}, args...);
}
template<typename F, typename Tuple, typename Head, typename... Tail, typename... Args>
T _call(F f, Tuple& t, types<Head, Tail...>, Args&&... args){
_call(f, t, types<Tail...>{}, std::forward<Args>(args)..., std::get<sizeof...(Arg)>(t).DrawSample()));
}
T _call(F f, Tuple& t, types<>, Args... vs){
return f(vs...)
}
};
我可以毫无困难地编译和运行上面的代码。现在我想让函数调用(...)被懒惰地调用。换句话说,我可以通过传入计算所需的所有参数来构造函数:
int getMax(float f1, float f2, float f3){
if(f1 >= f2 && f1 >= f3){
return 1;
}
if(f2 >= f1 && f2 >= f3){
return 2;
}
if(f3 >= f1 && f3 >= f2){
return 3;
}
}
Func<int> func;
//Gaussian(mu, sd) is an object which can generate random values based on Gaussian
//distribution described with mu(mean) and sd(standard deviation).
Gaussian *g1 = Gaussian(0.3, 0.2);
Gaussian *g2 = Gaussian(0.2, 0.3);
Gaussian *g3 = Gaussian(0.3, 0.3);
func.setCall(getMax, std::make_tuple(*g1, *g2, *g3);
cout<<func.DrawSample();
构造函数之后,我希望每次查询func.DrawSample()时都会懒惰地获取getMax()函数的结果。在引擎盖下,也许DrawSample()调用call(...)。但是,无论如何,我是否需要更改上面的代码才能创建一个setCall(...),其目的是存储以后函数调用所需的所有内容?
如果我的问题仍然不清楚,请告诉我。非常感谢你的帮助!
答案 0 :(得分:0)
使用std::function<int()>
和lambdas。
std::function<int()> func;
func = [=]()->int {
return getMax( Guassian(0.3,0.2), Guassian(0.2,0.3), Guassian(0.3,0.3) );
};
std::cout << func();
如果您确实需要自己的界面,只需在std::function<T()>
内存储class
,setCall
只需指定即可。
但实际上,您的对象是一些匿名类型,可以调用它来生成int
- std::function
解决问题。无论如何你都必须进行类型擦除,因为你的类的类型不包括函数签名,所以你可能不会更有效率。
答案 1 :(得分:0)
试试这个:
template<class Func, class... Args>
int applyDrawSample(Func func, Args... args)
{
return func(args.DrawSample()...);
}
template<class Func, class... Args>
auto bind_helper(Func func, Args... args)
-> decltype(bind(applyDrawSample<Func, Args...>, func, args...))
{
return bind(applyDrawSample<Func, Args...>, func, args...);
}
用法:
auto func = bind_helper(getMax, Gaussian(...), Gaussian(...), Gaussian(...));
func();
一个简单的额外lambda可以将最后一次调用更改为func->DrawSample()
,如果你真的想要它,并留作练习。
如果您需要上面func
的类型,则可以是std::function
:
function<int()> func = bind_helper(...);
int
的函数签名(在本例中为无参数的函数,返回std::function
)需要与您指定的内容兼容。
答案 2 :(得分:0)
根据DanielKO提供的建议,我终于为我的具体方案提出了一个解决方案。 这是我编译代码的最终版本。
template<class Func, class... Args>
int applyDrawSample(Func func, Args&&... args){
return func((*args).DrawSample()...);
}
template<class Func, class... Args>
auto bind_helper(Func func, Args&&... args) ->decltype(bind(applyDrawSample<Func, Args...>,
func, args...))
{
return bind(applyDrawSample<Func, Args...>, func, args...);
}
template<typename T>
struct UncertainFunc{
template<typename F, typename... Args>
void setFunc(F f, Args... args){
function = bind_helper(f, args...);
}
T DrawSample(){
return function();
}
std::function<T()> function;
};
UncertainFunc<int> ufunc;
ufunc.setFunc(getMax, &(Gaussian(0.3, 0.2), &Gaussian(0.2, 0.3), &Gaussian(0.2, 0.2));
ufunc.DrawSample();
特别是,由于某些原因(似乎是自动类型?),我似乎无法将bind_helper(...)函数放入我的类定义中。