Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.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++;11个函数承担函数<&燃气轮机;参数自动接受lambda_C++_C++11_Lambda - Fatal编程技术网

C++ 如何制作C++;11个函数承担函数<&燃气轮机;参数自动接受lambda

C++ 如何制作C++;11个函数承担函数<&燃气轮机;参数自动接受lambda,c++,c++11,lambda,C++,C++11,Lambda,C++11既有lambda函数又有std::函数,但不幸的是,它们有不同的类型。 一个结果是,不能在高阶函数中直接使用lambda,如lisp中的map。例如,在下面的代码中 #include <vector> #include <functional> using namespace std; template <typename A,typename B> vector<B> map(std::function<B (A)&

C++11既有lambda函数又有std::函数,但不幸的是,它们有不同的类型。 一个结果是,不能在高阶函数中直接使用lambda,如lisp中的map。例如,在下面的代码中

 #include <vector>
 #include <functional>
 using namespace std;

 template <typename A,typename B> 
 vector<B> map(std::function<B (A)> f, vector<A> arr) {
       vector<B> res;
       for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
       return res;
}

int main () {
    vector<int> a = {1,2,3};
    map([](int x) -> int { return x;},a); //not OK

    auto id_l = [](int x) -> int { return x;};
    map(id_l,a); //not OK;

    function<int (int)> id_f = id_l;
    map(id_f,a); //OK
return 0;
}
从上面可以清楚地看出,什么是
f
,它可以接受什么或不能接受什么。也许,一个人也可以使用

 //approach#2
 template <typename A,typename B, typename F> 
 auto fold_right2(F f, vector<A> arr, B b) -> decltype(f(???)) {
      ...
 }
撇开效率问题不谈,上面的代码很不方便,因为std::function不能接受lambda。所以

fold_right([](int x, int y) -> int { return x + y; },{1,2,3},0);

目前在C++11中不起作用。我的问题是,是否可以让上面定义的函数(如
fold_right
)直接接受lambda的。也许希望太多了。我希望这能澄清问题。

你的地图功能坏了。除非无法使用模板,否则不要使用
std::function
;在这种情况下,你绝对可以。您不需要将
B
作为模板参数,因为
decltype
可以将其提供给您,并且您根本不需要参数类型实际上是
std::function

template <typename A, typename F> auto map(F f, vector<A> arr) -> std::vector<decltype(f(arr.front())> {
    std::vector<decltype(f(arr.front())> res;
    for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
    return res;
}
模板自动映射(F,vector arr)->std::vector{
std::向量res;

对于(int i=0;i为什么首先要通过
std::function
创建一个动态间接寻址?只需在function对象上进行模板化,就可以进行排序:

template <typename A, typename F> 
auto map(F f, std::vector<A> arr) -> std::vector<decltype(f(arr[0]))> {
    std::vector<decltype(f(arr[0]))> res;
    for (int i=0; i<arr.size(); ++i)
        res.push_back(f(arr[i]));
    return res;
}
<>最后,请注意,标准C++库已经是一个“map”函数,它恰好拼写为“代码> STD::Trase:(/Cuth.>),并且具有一个适合C++中的通用方法的接口:

std::vector<int> result;
std::transform(a.begin(), a.end(), std::back_inserter(result),
               [](int x){ return x;});
std::向量结果;
std::transform(a.begin()、a.end()、std::back_插入器(result),
[](int x){return x;});
我的问题是如何使这样一个函数(带有
std::function
类型化参数)自动接受lambda的

你不能。为什么你认为这是可能的?
std::function
是标准库的一部分,除了其他类类型之外,它没有其他功能

此外,通过人为地将解决方案空间限制为以lambda为参数的函数调用和以
std::function
为参数的
T
,没有任何可能的更改。参数将与参数不匹配,并且您已经任意决定禁止更改这两个参数

给定一个来自_lambda
的函数
dynamic _function\u,将任何lambda封装在
std::function
中,您可以在函数调用或通过演绎接受lambda对象的函数体中显式执行转换

备选案文A:

map( dynamic_function_from_lambda( []( int a ){ return a + 1 } ), v );
备选案文B:

template< typename F, typename V >
std::vector< typename std::result_of< F( typename V::value_type ) >::type >
map( F f, V v )
    { return map( dynamic_function_from_lambda( f ), std::move( v ) ); }
模板
std::vector::type>
地图(F、V、V)
{返回映射(动态函数_from_lambda(f),std::move(v));}

但是,
std::function
的全部要点是运行时多态性,因此如果不使用它,它的效率会非常低。

最终找到了一个通用的包装函数
make_function
(在当前的c++11中)用于将任何lambda转换为其相应的
std::function
对象,并使用类型推断。现在不再使用ctor:

map(function<int (int)>( [](int x) -> int { return x;} ), {1,2,3});
map(function<int (int)>( [](int x) -> int { return x;} ), {1,2,3});
代码如下:

 #include <vector>
 #include <functional>
 using namespace std;

 template <typename T>
 struct function_traits
    : public function_traits<decltype(&T::operator())>
 {};

 template <typename ClassType, typename ReturnType, typename... Args>
 struct function_traits<ReturnType(ClassType::*)(Args...) const> {
    typedef function<ReturnType (Args...)> f_type;
 };

 template <typename L> 
 typename function_traits<L>::f_type make_function(L l){
   return (typename function_traits<L>::f_type)(l);
 }

 template <typename A,typename B> 
 vector<B> map(std::function<B (A)> f, vector<A> arr) {
       vector<B> res;
       for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
       return res;
}

int main () {
    vector<int> a = {1,2,3};
    map(make_function([](int x) -> int { return x;}),a); //now OK
    return 0;
}
#包括
#包括
使用名称空间std;
模板
结构功能特性
:公共职能
{};
模板
结构功能特性{
typedef函数f_type;
};
模板
类型名函数特征::f类型生成函数(L){
返回(typename函数类型::f类型)(l);
}
模板
向量映射(std::函数f,向量arr){
向量res;
对于(int i=0;i int{return x;}),a);//现在确定
返回0;
}
--原始答案--

经过几周的搜索(并因使用std::function作为参数而受到惩罚),要回答我自己的问题,我能找到的让函数类型的参数接受lambda(在c++11中)的最好方法可能是通过显式转换:

map((function<int (int)>) ([](int x) -> int { return x;} ), {1,2,3});
map((函数)([](int x)->int{return x;}),{1,2,3});
或使用ctor:

map(function<int (int)>( [](int x) -> int { return x;} ), {1,2,3});
map(function<int (int)>( [](int x) -> int { return x;} ), {1,2,3});
map(函数([](intx)->int{returnx;}),{1,2,3});
作为比较,如果您有一个函数使用std::string(例如,
void ff(string s){…}
),它可以自动使用
const char*
ff(“Hi”)
),从lambda到
std::function
的自动转换在c++11(不幸的是,IMO)中也不起作用


希望在c++14/1y中,当lambda可以正确类型化或更好地推导类型时,情况会有所改善。

事实上,您可以做到这一点,甚至比使用std::function更好(更快、更便宜)。它有一个堆alloc和一个虚拟函数调用。它只需要用于类型擦除(接受任何具有相同签名的可调用).但对于lambda,您不需要这种(昂贵的)灵活性。只需使用lambda包装类即可

#include <iostream>
#include <functional>
#include <vector>

template <typename T, typename ... Args>
struct lambda_wrapper : public lambda_wrapper<decltype(&T::operator())(Args...)> {
    using RetType = decltype(&T::operator())(Args...);
};

template <typename L>
struct lambda_wrapper<L> {
private:
    L lambda;

public:
    lambda_wrapper(const L & obj) : lambda(obj) {}

    template<typename... Args>
    typename std::result_of<L(Args...)>::type operator()(Args... a) {
        return this->lambda.operator()(std::forward<Args>(a)...);
    }

    template<typename... Args> typename
    std::result_of<const L(Args...)>::type operator()(Args... a) const {
        return this->lambda.operator()(std::forward<Args>(a)...);
    }
};
template <typename T>
auto make_lambda_wrapper(T&&t) {
    return lambda_wrapper<T>(std::forward<T>(t));
}

template <typename A, typename F>
auto map(F f, std::vector<A> arr)
{
    std::vector < decltype(f(arr.front())) > res;
    for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
    return res;
}

int main(int argc, char ** argv) {

    std::vector<int> a = {1,2,3};

    map(make_lambda_wrapper([](int a) -> int { return a*2;} ),a);

}
#包括
#包括
#包括
模板
结构lambda_包装器:公共lambda_包装器{
使用RetType=decltype(&T::operator())(Args;
};
模板
结构lambda_包装器{
私人:
L lambda;
公众:
lambda_包装器(const L&obj):lambda(obj){}
模板
typename std::result_of::type operator()(Args…a){
返回此->lambda.operator()(std::forward(a)…);
}
模板类型名
std::type operator()(Args…a)const的结果{
返回此->lambda.operator()(std::forward(a)…);
}
};
模板
自动生成lambda包装(T&T){
返回lambda_包装(std::forward(t));
}
模板
自动映射(F,标准::矢量arr)
{
std::vectorres;
对于(int i=0;i int{返回a*2;}),a);
}

您可以使用
&LambdaT::operator()
获取lambda参数,如下所示:

template <typename R, typename LambdaT, typename... Args>
auto _LambdaToStdFunction(LambdaT lambda, R (LambdaT::*)(Args...) const) {
  return std::function<R(Args...)>(lambda);
}
template <typename LambdaT>
auto LambdaToStdFunction(LambdaT &&lambda) {
  return _LambdaToStdFunction(std::forward<LambdaT>(lambda),
                              &LambdaT::operator());
}
模板
自动LambdaToStdFunction(LambdaT lambda,R(LambdaT::*)(Args…)常量){
返回std::函数(lambda);
}
#include <iostream>
#include <functional>
#include <vector>

template <typename T, typename ... Args>
struct lambda_wrapper : public lambda_wrapper<decltype(&T::operator())(Args...)> {
    using RetType = decltype(&T::operator())(Args...);
};

template <typename L>
struct lambda_wrapper<L> {
private:
    L lambda;

public:
    lambda_wrapper(const L & obj) : lambda(obj) {}

    template<typename... Args>
    typename std::result_of<L(Args...)>::type operator()(Args... a) {
        return this->lambda.operator()(std::forward<Args>(a)...);
    }

    template<typename... Args> typename
    std::result_of<const L(Args...)>::type operator()(Args... a) const {
        return this->lambda.operator()(std::forward<Args>(a)...);
    }
};
template <typename T>
auto make_lambda_wrapper(T&&t) {
    return lambda_wrapper<T>(std::forward<T>(t));
}

template <typename A, typename F>
auto map(F f, std::vector<A> arr)
{
    std::vector < decltype(f(arr.front())) > res;
    for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
    return res;
}

int main(int argc, char ** argv) {

    std::vector<int> a = {1,2,3};

    map(make_lambda_wrapper([](int a) -> int { return a*2;} ),a);

}
template <typename R, typename LambdaT, typename... Args>
auto _LambdaToStdFunction(LambdaT lambda, R (LambdaT::*)(Args...) const) {
  return std::function<R(Args...)>(lambda);
}
template <typename LambdaT>
auto LambdaToStdFunction(LambdaT &&lambda) {
  return _LambdaToStdFunction(std::forward<LambdaT>(lambda),
                              &LambdaT::operator());
}
#include <functional>
#include <iostream>
#include <vector>

template <typename LambdaT, typename R, typename... Args>
auto _LambdaToStdFunction(LambdaT lambda, R (LambdaT::*)(Args...) const) {
  return std::function<R(Args...)>(lambda);
}
template <typename LambdaT>
auto LambdaToStdFunction(LambdaT &&lambda) {
  return _LambdaToStdFunction(std::forward<LambdaT>(lambda),
                              &LambdaT::operator());
}

template <typename A, typename B>
std::vector<B> map(std::function<B(A)> f, std::vector<A> arr) {
  std::vector<B> res;
  for (int i = 0; i < arr.size(); i++) res.push_back(f(arr[i]));
  return res;
}

int main() {
  std::vector<int> a = {1, 2, 3};
  auto f = LambdaToStdFunction([](int x) -> int {
    std::cout << x << std::endl;
    return x;
  });
  map(LambdaToStdFunction([](int x) -> int {
        std::cout << x << std::endl;
        return x;
      }),
      a);  // now OK
  return 0;
}