0

我正在尝试使用变量模板编写自己的应用函数。这是我的代码:

    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...)
        }
    };

我可以毫无困难地编译和运行上面的代码。现在我想让函数 call(...) 被懒惰地调用。换句话说,我可以首先通过传入计算所需的所有参数来构造函数:

    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(...) ,其目的是存储以后函数调用所需的所有内容?

如果我的问题仍然不清楚,请告诉我。非常感谢你的帮助!

4

3 回答 3

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();

如果您真的非常需要您的界面,只需将 a 存储std::function<T()>在您的class中,然后setCall简单地分配给它。

但实际上,您的对象是一些匿名类型,可以调用它来产生int--std::function解决问题。无论如何,您都必须进行类型擦除,因为您的类的类型不包括函数签名,因此您可能不会更有效率。

于 2013-10-23T21:07:17.913 回答
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(...) 函数放入我的类定义中。

于 2013-10-24T16:07:05.713 回答
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(...);

函数签名(在这种情况下,一个没有参数的函数,返回一个intstd::function需要与您分配的内容兼容。

于 2013-10-23T21:55:37.800 回答