Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中用变量模板实现的apply函数的延迟求值+;_C++_Templates_Lazy Evaluation - Fatal编程技术网

C++ 在C+中用变量模板实现的apply函数的延迟求值+;

C++ 在C+中用变量模板实现的apply函数的延迟求值+;,c++,templates,lazy-evaluation,C++,Templates,Lazy Evaluation,我正在尝试使用变量模板编写自己的应用函数。以下是我的代码: template<typename...> struct types{ }; template<typename T, typename... Args> struct Func{ template<typename F, typanem... Types> T call(F f, std::tuple<Types...&

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

    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...)
        }
    };
模板
结构类型{
};
模板
结构函数{
模板
T调用(F,std::tuple¶ms,Args…Args){
返回_调用(f,参数,类型{},args…);
}
模板
T_调用(F、元组和T、类型、参数和…参数){
_调用(f,t,类型{},std::forward(args)…,std::get(t).DrawSample());
}
T_调用(F,Tuple&T,type,Args…vs){
返回f(对…)
}
};
我可以毫无困难地编译和运行上面的代码。现在我想让函数调用(…)被延迟调用。换句话说,我可以首先通过传入计算所需的所有参数来构造函数:

    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();
int getMax(浮点f1、浮点f2、浮点f3){
如果(f1>=f2&&f1>=f3){
返回1;
}
如果(f2>=f1&&f2>=f3){
返回2;
}
如果(f3>=f1&&f3>=f2){
返回3;
}
}
Func Func;
//高斯(mu,sd)是一种可以根据高斯分布生成随机值的对象
//用mu(平均值)和sd(标准偏差)描述的分布。
高斯*g1=高斯(0.3,0.2);
高斯*g2=高斯(0.2,0.3);
高斯*g3=高斯(0.3,0.3);
函数setCall(getMax,std::make_tuple(*g1,*g2,*g3);
不能使用
std::function
和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 func;
func=[=]()->int{
return getMax(Guassian(0.3,0.2)、Guassian(0.2,0.3)、Guassian(0.3,0.3));
};
std::cout试试这个:

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...);
}
如果您真的需要,一个微不足道的额外lambda可以将最后一个调用更改为类似于
func->DrawSample()
,并留作练习

编辑 如果您需要上面的
func
类型,它可以是
std::function

function<int()> func = bind_helper(...);
函数func=bind_helper(…);

std::function
的函数签名(在本例中,是一个没有参数的函数,返回一个
int
)需要与您分配的内容兼容。

根据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();
模板
int applyDrawSample(Func-Func,Args&&…Args){
返回func((*args.DrawSample()…);
}
模板
自动绑定辅助程序(Func-Func,Args&…Args)->decltype(绑定(applyDrawSample,
func,args…)
{
返回绑定(applyDrawSample、func、args…);
}
模板
结构不确定函数{
模板
void setFunc(F,Args…Args){
函数=bind_helper(f,args…);
}
抽签样本(){
返回函数();
}
std::函数;
};
不确定因素;
setFunc(getMax,&(高斯(0.3,0.2),&Gaussian(0.2,0.3),&Gaussian(0.2,0.2));
ufunc.DrawSample();

特别是,由于某种原因,我似乎无法将bind_helper(…)函数放入我的类定义中(可能是自动类型?)

每次调用
Gaussian::operator()
时是否要调用
getMax()
?能否告诉我们为什么
auto func=bind(getMax,Gaussian(0.3,0.2),Gaussian(0.2,0.3),Gaussian(0.3));
不能改用?有点。在我的Gaussian实现中,我定义了一个DrawSample()函数,每次提取一个浮点。getMax有声明getMax(float,float,float),而Gaussian是一个对象而不是一个浮点。你是否建议在Gaussian内部定义一个操作符而不是DrawSample()函数?谢谢你的回答。我确实需要这个接口,因为我不能期望什么样的函数可以作为Func的参数传入。在这个例子中,它是getMax,但它肯定可以是其他的。我认为getMax(Gaussian(…),Gaussian…,Gaussian…)不是一个有效的语句,因为getMax()的声明要求所有输入参数都应该是float,而不是GaussianThanks,这对您的响应非常有用。这一建议使实现更干净!我不太擅长lambda。因此,我还有一个后续问题。我可以将这两个函数放入我的类定义中。但是,有什么方法可以这样做吗我可以将bind_helper的返回值以某种方式存储为一个成员,这样以后我就可以一次又一次地调用它了?为了让问题更清楚,有什么方法可以将func保存为类的一个成员字段吗?或者我可以用其他方法来保存它,比如你回答中提到的额外lambda?我不知道怎么做。谢谢!
    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();