Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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?_C++_Function_Closures_Local_Functor - Fatal编程技术网

C++ 是否可以在C+;之前创建函数本地闭包+;11?

C++ 是否可以在C+;之前创建函数本地闭包+;11?,c++,function,closures,local,functor,C++,Function,Closures,Local,Functor,有了C++11,我们就有了lambda,可以在实际需要的地方动态创建函数/函子/闭包,而不是在它们不属于的地方。 在C++98/03中,创建函数局部函子/闭包的一个好方法是: struct{ void operator()(int& item){ ++item; } }foo_functor; some_templated_func(some_args, foo_functor); 遗憾的是,您不能为模板使用本地类型(VisualStudio允许在启用语言扩展的情况下使用)。我的思

有了C++11,我们就有了lambda,可以在实际需要的地方动态创建函数/函子/闭包,而不是在它们不属于的地方。
在C++98/03中,创建函数局部函子/闭包的一个好方法是:

struct{
  void operator()(int& item){ ++item; }
}foo_functor;
some_templated_func(some_args, foo_functor);
遗憾的是,您不能为模板使用本地类型(VisualStudio允许在启用语言扩展的情况下使用)。我的思路是这样的:

struct X{
  static void functor(int& item){ ++item; }
};
some_templated_func(some_args, &X::functor);
明显的问题是,您无法保存任何状态,因为本地结构/类不能有静态成员。
我解决这个问题的下一个想法是混合使用
std::bind1st
std::mem_-fun
以及非静态方法和变量,但不幸的是
std::mem_-fun
不知何故被
std::mem_-fn(&X::functor)
阻塞了,这同样可能是因为本地结构/类不能在模板中使用:

// wanted, not working solution
struct X{
  int n_;
  X(int n) : n_(n) {}
  void functor(int& item) const { item += n_; }
};
X x(5);
some_templated_func(some_args,std::bind1st(std::mem_fun(&X::functor),&x));
在VC9和VC10下失败(带有
/Za
,禁用了语言扩展),出现以下错误

error C2893: Failed to specialize function template 'std::const_mem_fun1_t<_Result,_Ty,_Arg> std::mem_fun(_Result (_Ty::* )(_Arg) const)'
With the following template arguments:
'void'
'main::X'
'int &'
有趣的是,VC9/VC10仍然受上述示例的限制,即使使用语言扩展也可以:

error C2535: 'void std::binder1st<_Fn2>::operator ()(int &) const' : member function already defined or declared
错误C2535:'void std::binder1st::operator()(int&)const':成员函数已定义或声明

那么,标题中所述的功能是否可以实现?或者在上一个示例中,我在如何使用
std::bind1st
std::mem\u fun
时犯了错误?

如果这在C++03中是可行的,为什么C++0x会引入lambdas?lambda的存在是有原因的,这是因为binding和所有其他的C++03解决方案都非常糟糕。

bind1st
只适用于二进制函数,一般来说它非常有限
mem_fn
仅适用于非静态成员函数;对于您的应用程序,您需要
ptr\u fun

实际上,在C++03中,最好的工具是boostbind,或者我将在这里用
tr1::Bind
演示,它(在我看来)更易于移植

#include <tr1/functional>
#include <iostream>
#include <algorithm>

using namespace std::tr1::placeholders;

int nums[] = { 1, 2, 4, 5, 6, 8 };

int main() {
    struct is_multiple {
        static bool fn( int mod, int num ) { return num % mod == 0; }
    };

    int *n = std::find_if( nums, nums + sizeof nums/sizeof*nums,
                        std::tr1::bind( is_multiple::fn, 3, _1 ) );

    std::cout << n - nums << '\n';
}
#包括
#包括
#包括
使用名称空间std::tr1::占位符;
int nums[]={1,2,4,5,6,8};
int main(){
结构是多个{
静态bool fn(int mod,int num){return num%mod==0;}
};
int*n=std::find_if(nums,nums+sizeof nums/sizeof*nums,
std::tr1::bind(是多个::fn,3,_1));

std::cout是的,您可以,但是您必须实现一个或多个在接口中声明的虚拟方法

template<typename Arg, typename Result>
struct my_unary_function
{
    virtual Result operator()(Arg) = 0;
};

template<typename Arg, typename Result>
struct my_unary_functor
{
    my_unary_function<Arg, Result> m_closure;
    my_unary_functor(my_unary_function<Arg, Result> closure) : m_closure(closure) {}
    Result operator()(Arg a) { return m_closure(a); }
};

template<typename T, TFunctor>
void some_templated_function( std::vector<T> items, TFunctor actor );


好的,可能是C++0x刚刚引入了一种更简单的解决方案。:)例如,C++0x中的Range For构造在C++03中完全可行,但Range For非常好。这里的想法是正确的,但推理是错误的。如果可行,我们现在可能会在C++03中如何伪造它,但我们没有。(即使我们可以,C++0x仍然会添加更好的语法。)@Omnifarious:ranged for loop是一个可怕的语言构造,有很多原因。@GMan:Standard committee不会浪费时间介绍非问题的解决方案。好吧,Range for loop被排除在外。@DeadMG:为什么Range for loop是这样一个可怕的东西?如果它是本地类,你将如何使用它?你不能将它传递给任何其他函数(除了作为一个
无效*
?).这是我在问题中提到的第一个例子,如果是本地类/结构,你不能将该函子传递给在函子上模板化的函数。.@Ben:啊,我忘了!实际上我在非模板上下文中使用过这个习惯用法,但不,这不适用于OP的问题。@Xeo:啊,现在我更好地理解了你的目的,为什么你想使用
bind1st
。是的,
bind1st
应该可以解决你的问题,如果你能让它正常工作的话。问题是它太痛苦了。我会重新编写一点答案。编辑的版本非常像我想要的。很遗憾,你需要整个绑定的东西,但至少它可以让你模拟函数本地closur有点合理。谢谢!:)
std::mem\u fn(&X::functor)
阻塞,因为
functor
不是成员函数,它是静态的。@GMan:不,不是在最后一个示例中。@Xeo:对不起,我的意思是回答“但不幸的是std::mem\u fun不知怎么阻塞了…”,在第二个中。@Xeo:它必须是静态的,否则你会得到一个指向本地类型成员的指针,这不是一个有效的模板参数。请尝试使用
std::ptr_fun
,然后使用
bind_1st
传递实际捕获的值,而不是本地类型的实例。@GMan:啊,是的,应该有一个新的段落和一个双冒号,s对不起。我想我知道你在说什么,这会起作用的,但它有点难看和慢。是的,这几乎正是我所想的。啊,我现在明白了。但是这需要我将我想要使用的每个模板函数包装在一个新函数中,这个新函数需要一个
我的一元函数
,对吗?@Xeo:假设是您正在调用的算法已经设计为使用接口。如果它是为functor设计的,那就不太好了,但我相信您可以构建一个非本地functor/接口适配器类,然后不需要单独包装每个函数。@Xeo:不一定。您可以创建这样的临时函数:
my_一元函数&expr=closure(1,5)
然后传递该临时值。它的类型将是正确的类型,并且您不必调用特殊版本的模板函数。@Omni:啊,没错。是的,这当然解决了编写包装函数的问题。谢谢。
template<typename Arg, typename Result>
struct my_unary_function
{
    virtual Result operator()(Arg) = 0;
};

template<typename Arg, typename Result>
struct my_unary_functor
{
    my_unary_function<Arg, Result> m_closure;
    my_unary_functor(my_unary_function<Arg, Result> closure) : m_closure(closure) {}
    Result operator()(Arg a) { return m_closure(a); }
};

template<typename T, TFunctor>
void some_templated_function( std::vector<T> items, TFunctor actor );
void f()
{
    std::vector<int> collection;

    struct closure : my_unary_function<int, int>
    {
        int m_x, m_y;
        closure(int x, int y) : m_x(x), m_y(y) {}
        virtual int operator()(int i) const { cout << m_x + m_y*i << "\t"; return (m_x - m_y) * i; }
    };

    some_templated_function( collection, my_unary_functor<int,int>(closure(1, 5)) );
}
void f()
{
    std::vector<int> collection;

    struct closure : my_unary_function<int, int>
    {
        int m_x, m_y;
        closure(int x, int y) : m_x(x), m_y(y) {}
        virtual int operator()(int i) const { cout << m_x + m_y*i << "\t"; return (m_x - m_y) * i; }
    };

    // need a const reference here, to bind to a temporary
    const my_unary_functor<int,int>& closure_1_5 = my_unary_functor<int,int>(closure(1, 5))
    some_templated_function( collection, closure_1_5 );
}